@okxweb3/a2a-node 0.2.18-beta-4dd056b897-261015113839 → 0.2.18

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 (3) hide show
  1. package/dist/cli.js +708 -1849
  2. package/dist/index.js +704 -1745
  3. package/package.json +4 -4
package/dist/index.js CHANGED
@@ -4008,7 +4008,7 @@ var require_is = __commonJS({
4008
4008
  function isPrimitive(wat) {
4009
4009
  return wat === null || typeof wat !== "object" && typeof wat !== "function";
4010
4010
  }
4011
- function isPlainObject6(wat) {
4011
+ function isPlainObject4(wat) {
4012
4012
  return isBuiltin(wat, "Object");
4013
4013
  }
4014
4014
  function isEvent(wat) {
@@ -4024,7 +4024,7 @@ var require_is = __commonJS({
4024
4024
  return Boolean(wat && wat.then && typeof wat.then === "function");
4025
4025
  }
4026
4026
  function isSyntheticEvent(wat) {
4027
- return isPlainObject6(wat) && "nativeEvent" in wat && "preventDefault" in wat && "stopPropagation" in wat;
4027
+ return isPlainObject4(wat) && "nativeEvent" in wat && "preventDefault" in wat && "stopPropagation" in wat;
4028
4028
  }
4029
4029
  function isNaN2(wat) {
4030
4030
  return typeof wat === "number" && wat !== wat;
@@ -4047,7 +4047,7 @@ var require_is = __commonJS({
4047
4047
  exports2.isEvent = isEvent;
4048
4048
  exports2.isInstanceOf = isInstanceOf;
4049
4049
  exports2.isNaN = isNaN2;
4050
- exports2.isPlainObject = isPlainObject6;
4050
+ exports2.isPlainObject = isPlainObject4;
4051
4051
  exports2.isPrimitive = isPrimitive;
4052
4052
  exports2.isRegExp = isRegExp;
4053
4053
  exports2.isString = isString;
@@ -19310,23 +19310,6 @@ var init_events = __esm({
19310
19310
  XMTP_RATE_LIMIT_CREATE_SUPPRESSED: "XMTP rate limit create suppressed",
19311
19311
  XMTP_RATE_LIMIT_PROBE: "XMTP rate limit probe",
19312
19312
  XMTP_RATE_LIMIT_RECOVERED: "XMTP rate limit recovered",
19313
- // ── subscription observability info (DEXMARKET-9096) ───────────
19314
- // All of the following logger.info checkpoints MUST also be listed in
19315
- // SENTRY_INFO_ALLOWLIST (index.ts): info() returns early for an unlisted
19316
- // event, which ships a checkpoint that looks implemented but emits nothing.
19317
- SUBSCRIPTION_PUSH_STARTED: "Subscription push started",
19318
- SUBSCRIPTION_PUSH_TARGETS_RESOLVED: "Subscription push targets resolved",
19319
- SUBSCRIPTION_PUSH_EMPTY_TARGETS: "Subscription push empty targets",
19320
- SUBSCRIPTION_PUSH_SUMMARY: "Subscription push summary",
19321
- SUBSCRIPTION_INBOUND_RECEIVED: "Subscription inbound received",
19322
- SUBSCRIPTION_INBOUND_GATE_DROPPED: "Subscription inbound gate dropped",
19323
- SUBSCRIPTION_JOBS_QUERY_STARTED: "Subscription jobs query started",
19324
- SUBSCRIPTION_JOBS_QUERY_SUCCEEDED: "Subscription jobs query succeeded",
19325
- SUBSCRIPTION_JOBS_EMPTY: "Subscription jobs empty",
19326
- SUBSCRIPTION_INBOUND_OWNERSHIP_ROUTED: "Subscription inbound ownership routed",
19327
- SUBSCRIPTION_JOB_DISPATCHED: "Subscription job dispatched",
19328
- SUBSCRIPTION_JOB_DUPLICATE_IGNORED: "Subscription job duplicate ignored",
19329
- SUBSCRIPTION_FANOUT_SUMMARY: "Subscription fan-out summary",
19330
19313
  // ── error ─────────────────────────────────────────────────────
19331
19314
  XMTP_CONNECTION_FAILED: "XMTP connection failed",
19332
19315
  CONVERSATIONS_STREAM_FAILED: "conversations.stream failed",
@@ -19393,13 +19376,6 @@ var init_events = __esm({
19393
19376
  AGENT_INSTALLATION_LIMIT_NEAR: "Agent installation limit near",
19394
19377
  XMTP_HISTORY_SYNC_REQUEST_FAILED: "XMTP history sync request failed",
19395
19378
  XMTP_DEBUG_SYNC_FAILED: "XMTP debug sync failed",
19396
- // ── subscription observability error (DEXMARKET-9096) ──────────
19397
- // error-level: always emitted (no allowlist gate). Error objects are
19398
- // classified by buildErrorDiagnostics — never attach raw Error.message.
19399
- SUBSCRIPTION_PUSH_TARGET_FAILED: "Subscription push target failed",
19400
- SUBSCRIPTION_INBOUND_AGENTIC_ID_MISSING: "Subscription inbound agenticId missing",
19401
- SUBSCRIPTION_JOBS_FAIL_CLOSED: "Subscription jobs fail closed",
19402
- SUBSCRIPTION_JOB_FAILED: "Subscription job failed",
19403
19379
  // Underlying XMTP SDK client close failed during recycle/removal/shutdown
19404
19380
  // (DEXMARKET-9116). Error-level → NOT added to SENTRY_INFO_ALLOWLIST.
19405
19381
  XMTP_CLIENT_CLOSE_FAILED: "XMTP client close failed"
@@ -19463,7 +19439,7 @@ function resolveDeliveryId(input) {
19463
19439
  if (slots.every((slot) => slot === "")) {
19464
19440
  return UNKNOWN_LOG_FIELD;
19465
19441
  }
19466
- const digest = (0, import_node_crypto3.createHash)("sha256").update(slots.join("|")).digest("hex");
19442
+ const digest = (0, import_node_crypto2.createHash)("sha256").update(slots.join("|")).digest("hex");
19467
19443
  return `${DERIVED_DELIVERY_ID_PREFIX}${digest.slice(0, DERIVED_DELIVERY_ID_LENGTH)}`;
19468
19444
  }
19469
19445
  function releaseFields(release) {
@@ -19581,11 +19557,11 @@ function enrichCorrelationFields(extra) {
19581
19557
  }
19582
19558
  return enriched;
19583
19559
  }
19584
- var import_node_crypto3, PROBE_NAME_PATTERN, PROBE_JOB_ID_PATTERN, XMTP_MESSAGE_ID_PATTERN, DERIVED_DELIVERY_ID_PREFIX, DERIVED_DELIVERY_ID_LENGTH, RELEASE_CODE_MAJOR_WEIGHT, RELEASE_CODE_MINOR_WEIGHT, UNKNOWN_LOG_FIELD, UNPARSABLE_RELEASE;
19560
+ var import_node_crypto2, PROBE_NAME_PATTERN, PROBE_JOB_ID_PATTERN, XMTP_MESSAGE_ID_PATTERN, DERIVED_DELIVERY_ID_PREFIX, DERIVED_DELIVERY_ID_LENGTH, RELEASE_CODE_MAJOR_WEIGHT, RELEASE_CODE_MINOR_WEIGHT, UNKNOWN_LOG_FIELD, UNPARSABLE_RELEASE;
19585
19561
  var init_log_fields = __esm({
19586
19562
  "../core/src/sentry-logger/log-fields.ts"() {
19587
19563
  "use strict";
19588
- import_node_crypto3 = require("node:crypto");
19564
+ import_node_crypto2 = require("node:crypto");
19589
19565
  PROBE_NAME_PATTERN = /probe/i;
19590
19566
  PROBE_JOB_ID_PATTERN = /^probe[-_]/i;
19591
19567
  XMTP_MESSAGE_ID_PATTERN = /^[0-9a-f]{16,}$/i;
@@ -19973,9 +19949,6 @@ function applyFatalEventDefaults(event) {
19973
19949
  function isInfoEventAllowlisted(name) {
19974
19950
  return SENTRY_INFO_ALLOWLIST.has(name);
19975
19951
  }
19976
- function isFingerprintKey(key) {
19977
- return SENTRY_FINGERPRINT_KEYS.includes(key);
19978
- }
19979
19952
  function isTagKey(key) {
19980
19953
  return SENTRY_TAG_KEYS.has(key);
19981
19954
  }
@@ -19987,13 +19960,13 @@ function agentExtras(identity) {
19987
19960
  role: identity.role != null && identity.role !== "" ? String(identity.role) : UNKNOWN_FIELD
19988
19961
  };
19989
19962
  }
19990
- var Sentry, import_node_crypto4, FLOW_ID, SENTRY_EXTRA_BLOCKLIST, SENTRY_EXTRA_BLOCKED_KEY_PARTS, SENTRY_FULL_STRING_EXTRA_KEYS, SENTRY_TAG_KEYS, SENTRY_FINGERPRINT_KEYS, SENTRY_INFO_ALLOWLIST, MAX_EXTRA_STRING_LENGTH, MAX_TAG_VALUE_LENGTH, RELEASE_FIELDS, RUNTIME_FIELDS, SentryLogger, logger, initLogger, shutdown, UNKNOWN_FIELD;
19963
+ var Sentry, import_node_crypto3, FLOW_ID, SENTRY_EXTRA_BLOCKLIST, SENTRY_EXTRA_BLOCKED_KEY_PARTS, SENTRY_FULL_STRING_EXTRA_KEYS, SENTRY_TAG_KEYS, SENTRY_FINGERPRINT_KEYS, SENTRY_INFO_ALLOWLIST, MAX_EXTRA_STRING_LENGTH, MAX_TAG_VALUE_LENGTH, RELEASE_FIELDS, RUNTIME_FIELDS, SentryLogger, logger, initLogger, shutdown, UNKNOWN_FIELD;
19991
19964
  var init_sentry_logger = __esm({
19992
19965
  "../core/src/sentry-logger/index.ts"() {
19993
19966
  "use strict";
19994
19967
  init_log();
19995
19968
  Sentry = __toESM(require_cjs4());
19996
- import_node_crypto4 = require("node:crypto");
19969
+ import_node_crypto3 = require("node:crypto");
19997
19970
  init_events();
19998
19971
  init_log_fields();
19999
19972
  init_xmtp_test_metrics();
@@ -20001,7 +19974,7 @@ var init_sentry_logger = __esm({
20001
19974
  init_runtime_metadata();
20002
19975
  init_events();
20003
19976
  init_log_fields();
20004
- FLOW_ID = (0, import_node_crypto4.randomUUID)();
19977
+ FLOW_ID = (0, import_node_crypto3.randomUUID)();
20005
19978
  SENTRY_EXTRA_BLOCKLIST = /* @__PURE__ */ new Set([
20006
19979
  "args",
20007
19980
  "apikey",
@@ -20084,13 +20057,6 @@ var init_sentry_logger = __esm({
20084
20057
  ]);
20085
20058
  SENTRY_TAG_KEYS = /* @__PURE__ */ new Set([
20086
20059
  "agentId",
20087
- // Subscription correlation agent ids (DEXMARKET-9096). Bounded-cardinality,
20088
- // same class as agentId/senderAgentId/onchainosAgentId — promoted to indexed
20089
- // tags for Sentry filtering. NOT added to SENTRY_FINGERPRINT_KEYS, so the
20090
- // global issue fingerprint is unchanged. High-cardinality ids
20091
- // (conversationId/messageId/deliveryId) are deliberately NOT here.
20092
- "aspAgentId",
20093
- "userAgentId",
20094
20060
  "agentPlatform",
20095
20061
  "aiProvider",
20096
20062
  "cacheName",
@@ -20258,22 +20224,6 @@ var init_sentry_logger = __esm({
20258
20224
  LogEvent.SESSION_KEY_DERIVED,
20259
20225
  LogEvent.SESSIONS_QUERIED,
20260
20226
  LogEvent.SYNC_TICK_COMPLETED,
20261
- // Subscription observability info checkpoints (DEXMARKET-9096). Each is a
20262
- // logger.info event; omitting any makes info() drop it silently so the whole
20263
- // subscription trace would look implemented and emit nothing in production.
20264
- LogEvent.SUBSCRIPTION_PUSH_STARTED,
20265
- LogEvent.SUBSCRIPTION_PUSH_TARGETS_RESOLVED,
20266
- LogEvent.SUBSCRIPTION_PUSH_EMPTY_TARGETS,
20267
- LogEvent.SUBSCRIPTION_PUSH_SUMMARY,
20268
- LogEvent.SUBSCRIPTION_INBOUND_RECEIVED,
20269
- LogEvent.SUBSCRIPTION_INBOUND_GATE_DROPPED,
20270
- LogEvent.SUBSCRIPTION_JOBS_QUERY_STARTED,
20271
- LogEvent.SUBSCRIPTION_JOBS_QUERY_SUCCEEDED,
20272
- LogEvent.SUBSCRIPTION_JOBS_EMPTY,
20273
- LogEvent.SUBSCRIPTION_INBOUND_OWNERSHIP_ROUTED,
20274
- LogEvent.SUBSCRIPTION_JOB_DISPATCHED,
20275
- LogEvent.SUBSCRIPTION_JOB_DUPLICATE_IGNORED,
20276
- LogEvent.SUBSCRIPTION_FANOUT_SUMMARY,
20277
20227
  // XMTP creation rate-limit cooldown checkpoints (DEXMARKET-9116). info() drops
20278
20228
  // any event not listed here, so these must stay registered.
20279
20229
  LogEvent.XMTP_RATE_LIMIT_COOLDOWN_STARTED,
@@ -22229,7 +22179,7 @@ var require_retry_promise = __commonJS({
22229
22179
  return true;
22230
22180
  }
22231
22181
  };
22232
- function wait3(ms) {
22182
+ function wait2(ms) {
22233
22183
  return __awaiter(this, void 0, void 0, function() {
22234
22184
  return __generator(this, function(_a) {
22235
22185
  return [2, new Promise(function(resolve11) {
@@ -22238,7 +22188,7 @@ var require_retry_promise = __commonJS({
22238
22188
  });
22239
22189
  });
22240
22190
  }
22241
- exports2.wait = wait3;
22191
+ exports2.wait = wait2;
22242
22192
  function retry2(f, config) {
22243
22193
  return __awaiter(this, void 0, void 0, function() {
22244
22194
  var effectiveConfig;
@@ -22328,7 +22278,7 @@ var require_retry_promise = __commonJS({
22328
22278
  return [3, 5];
22329
22279
  case 5:
22330
22280
  millisToWait = delay(i + 1, config.delay);
22331
- return [4, wait3(millisToWait > config.maxBackOff ? config.maxBackOff : millisToWait)];
22281
+ return [4, wait2(millisToWait > config.maxBackOff ? config.maxBackOff : millisToWait)];
22332
22282
  case 6:
22333
22283
  _a.sent();
22334
22284
  if (done()) {
@@ -28811,7 +28761,7 @@ var init_withResolvers = __esm({
28811
28761
  });
28812
28762
 
28813
28763
  // ../../node_modules/viem/_esm/utils/promise/createBatchScheduler.js
28814
- function createBatchScheduler({ fn, id, shouldSplitBatch, wait: wait3 = 0, sort }) {
28764
+ function createBatchScheduler({ fn, id, shouldSplitBatch, wait: wait2 = 0, sort }) {
28815
28765
  const exec2 = async () => {
28816
28766
  const scheduler = getScheduler();
28817
28767
  flush2();
@@ -28849,7 +28799,7 @@ function createBatchScheduler({ fn, id, shouldSplitBatch, wait: wait3 = 0, sort
28849
28799
  return promise;
28850
28800
  }
28851
28801
  setScheduler({ args, resolve: resolve11, reject });
28852
- setTimeout(exec2, wait3);
28802
+ setTimeout(exec2, wait2);
28853
28803
  return promise;
28854
28804
  }
28855
28805
  };
@@ -31065,7 +31015,7 @@ var require_websocket2 = __commonJS({
31065
31015
  var http2 = require("http");
31066
31016
  var net = require("net");
31067
31017
  var tls = require("tls");
31068
- var { randomBytes: randomBytes3, createHash: createHash7 } = require("crypto");
31018
+ var { randomBytes: randomBytes3, createHash: createHash6 } = require("crypto");
31069
31019
  var { Duplex, Readable } = require("stream");
31070
31020
  var { URL: URL2 } = require("url");
31071
31021
  var PerMessageDeflate = require_permessage_deflate();
@@ -31725,7 +31675,7 @@ var require_websocket2 = __commonJS({
31725
31675
  abortHandshake(websocket, socket, "Invalid Upgrade header");
31726
31676
  return;
31727
31677
  }
31728
- const digest = createHash7("sha1").update(key + GUID).digest("base64");
31678
+ const digest = createHash6("sha1").update(key + GUID).digest("base64");
31729
31679
  if (res.headers["sec-websocket-accept"] !== digest) {
31730
31680
  abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
31731
31681
  return;
@@ -32092,7 +32042,7 @@ var require_websocket_server = __commonJS({
32092
32042
  var EventEmitter2 = require("events");
32093
32043
  var http2 = require("http");
32094
32044
  var { Duplex } = require("stream");
32095
- var { createHash: createHash7 } = require("crypto");
32045
+ var { createHash: createHash6 } = require("crypto");
32096
32046
  var extension = require_extension();
32097
32047
  var PerMessageDeflate = require_permessage_deflate();
32098
32048
  var subprotocol = require_subprotocol();
@@ -32393,7 +32343,7 @@ var require_websocket_server = __commonJS({
32393
32343
  );
32394
32344
  }
32395
32345
  if (this._state > RUNNING) return abortHandshake(socket, 503);
32396
- const digest = createHash7("sha1").update(key + GUID).digest("base64");
32346
+ const digest = createHash6("sha1").update(key + GUID).digest("base64");
32397
32347
  const headers = [
32398
32348
  "HTTP/1.1 101 Switching Protocols",
32399
32349
  "Upgrade: websocket",
@@ -32515,7 +32465,7 @@ var init_sentry_config = __esm({
32515
32465
  environment = process.env.SENTRY_ENV === "dev" ? "dev" : "prod";
32516
32466
  SENTRY_CONFIG = {
32517
32467
  projectName: "okx/openclaw-okx-a2a-extension",
32518
- release: "0.2.18-beta-4dd056b897-261015113839",
32468
+ release: "0.2.18",
32519
32469
  environment,
32520
32470
  runtimeContainer: normalizeRuntimeContainer(process.env.OKX_A2A_RUNTIME_CONTAINER)
32521
32471
  };
@@ -33471,7 +33421,7 @@ async function getCurrentNodeCliVersion() {
33471
33421
  return await getGlobalNpmPackageVersion(UPDATE_PACKAGES.node) ?? getBundledNodeCliVersion();
33472
33422
  }
33473
33423
  function getBundledNodeCliVersion() {
33474
- return true ? "0.2.18-beta-4dd056b897-261015113839" : null;
33424
+ return true ? "0.2.18" : null;
33475
33425
  }
33476
33426
  function readConfiguredAiProvider() {
33477
33427
  const explicit = process.env.OKX_A2A_AI_PROVIDER || process.env.OKX_AGENT_TASK_AI_CLI;
@@ -33681,7 +33631,7 @@ async function updateHermes(release, options) {
33681
33631
  }
33682
33632
  }
33683
33633
  async function installGatewayPluginForDoctor(target) {
33684
- const release = isPrereleaseVersion("0.2.18-beta-4dd056b897-261015113839") ? "beta" : "latest";
33634
+ const release = isPrereleaseVersion("0.2.18") ? "beta" : "latest";
33685
33635
  const insideTargetGateway = detectGatewayInvocation() === target;
33686
33636
  const options = {
33687
33637
  restart: !insideTargetGateway,
@@ -44403,7 +44353,6 @@ __export(index_exports, {
44403
44353
  InboundReplayGate: () => InboundReplayGate,
44404
44354
  InvalidXmtpMessageStore: () => InvalidXmtpMessageStore,
44405
44355
  JOB_PROVIDER_BINDING_SOURCES: () => JOB_PROVIDER_BINDING_SOURCES,
44406
- LIST_JOBS_BY_VERIFIED_SENDER_HELP_TOKEN: () => LIST_JOBS_BY_VERIFIED_SENDER_HELP_TOKEN,
44407
44356
  ListenerDeferredTaskScheduler: () => ListenerDeferredTaskScheduler,
44408
44357
  ListenerMaintenanceGate: () => ListenerMaintenanceGate,
44409
44358
  LogEvent: () => LogEvent,
@@ -44413,9 +44362,6 @@ __export(index_exports, {
44413
44362
  NATIVE_LAUNCHER_EXE_NAME: () => NATIVE_LAUNCHER_EXE_NAME,
44414
44363
  OPENCLAW_GATEWAY_ROUTE_GROUP_ID: () => OPENCLAW_GATEWAY_ROUTE_GROUP_ID,
44415
44364
  ProviderNotReadyError: () => ProviderNotReadyError,
44416
- RUN_LOG_FILENAME_MAX_BYTES: () => RUN_LOG_FILENAME_MAX_BYTES,
44417
- SUBSCRIPTION_FANOUT_MAX: () => SUBSCRIPTION_FANOUT_MAX,
44418
- SUBSCRIPTION_MESSAGE_TYPE: () => SUBSCRIPTION_MESSAGE_TYPE,
44419
44365
  SYSTEM_NOTIFICATION_SESSION_KEY: () => SYSTEM_NOTIFICATION_SESSION_KEY,
44420
44366
  SessionBusyTracker: () => SessionBusyTracker,
44421
44367
  SessionStore: () => SessionStore,
@@ -44461,9 +44407,7 @@ __export(index_exports, {
44461
44407
  buildInboundTerminalExtras: () => buildInboundTerminalExtras,
44462
44408
  buildLaunchdPlist: () => buildLaunchdPlist,
44463
44409
  buildLauncherEntryJs: () => buildLauncherEntryJs,
44464
- buildListJobsByVerifiedSenderArgs: () => buildListJobsByVerifiedSenderArgs,
44465
44410
  buildMessageEligibleArgs: () => buildMessageEligibleArgs,
44466
- buildRunLogFileName: () => buildRunLogFileName,
44467
44411
  buildSchtasksCreateArgs: () => buildSchtasksCreateArgs,
44468
44412
  buildSchtasksDeleteArgs: () => buildSchtasksDeleteArgs,
44469
44413
  buildSchtasksEndArgs: () => buildSchtasksEndArgs,
@@ -44472,14 +44416,9 @@ __export(index_exports, {
44472
44416
  buildSeaConfig: () => buildSeaConfig,
44473
44417
  buildServicePath: () => buildServicePath,
44474
44418
  buildSessionKey: () => buildSessionKey,
44475
- buildSubscriptionEnvelope: () => buildSubscriptionEnvelope,
44476
- buildSubscriptionInboundExtras: () => buildSubscriptionInboundExtras,
44477
- buildSubscriptionJobExtras: () => buildSubscriptionJobExtras,
44478
- buildSubscriptionSendExtras: () => buildSubscriptionSendExtras,
44479
44419
  buildSystemMessageNotice: () => buildSystemMessageNotice,
44480
44420
  buildSystemStoredMessage: () => buildSystemStoredMessage,
44481
44421
  buildSystemdUserService: () => buildSystemdUserService,
44482
- buildUpgradeRecommendationNotice: () => buildUpgradeRecommendationNotice,
44483
44422
  buildWin32OnchainosCandidates: () => buildWin32OnchainosCandidates,
44484
44423
  buildWindowsParentProcessProbe: () => buildWindowsParentProcessProbe,
44485
44424
  buildXmtpMessageSentExtra: () => buildXmtpMessageSentExtra,
@@ -44494,7 +44433,6 @@ __export(index_exports, {
44494
44433
  checkCodexReadiness: () => checkCodexReadiness,
44495
44434
  claimActiveDaemon: () => claimActiveDaemon,
44496
44435
  classifyJobBindingSource: () => classifyJobBindingSource,
44497
- classifyListJobsError: () => classifyListJobsError,
44498
44436
  clearCodexReadinessCache: () => clearCodexReadinessCache,
44499
44437
  codexCommandResolvesWithoutOverride: () => codexCommandResolvesWithoutOverride,
44500
44438
  codexReadinessCacheKey: () => codexReadinessCacheKey,
@@ -44506,12 +44444,10 @@ __export(index_exports, {
44506
44444
  createOutboundBehavior: () => createOutboundBehavior,
44507
44445
  createUserAttentionWatchParentMonitor: () => createUserAttentionWatchParentMonitor,
44508
44446
  currentOpenClawGatewaySessionKey: () => currentOpenClawGatewaySessionKey,
44509
- decideSubscriptionGate: () => decideSubscriptionGate,
44510
44447
  detectAiProviders: () => detectAiProviders,
44511
44448
  detectAiRuntimeSurface: () => detectAiRuntimeSurface,
44512
44449
  detectCurrentAiProvider: () => detectCurrentAiProvider,
44513
44450
  detectGatewayInvocation: () => detectGatewayInvocation,
44514
- detectListJobsByVerifiedSenderSupport: () => detectListJobsByVerifiedSenderSupport,
44515
44451
  detectMessageEligibleOfflineReplaySupport: () => detectMessageEligibleOfflineReplaySupport,
44516
44452
  detectRuntime: () => detectRuntime,
44517
44453
  ensureDaemonReady: () => ensureDaemonReady,
@@ -44525,7 +44461,6 @@ __export(index_exports, {
44525
44461
  extractDirectToUserNotification: () => extractDirectToUserNotification,
44526
44462
  extractRateLimitEndpoint: () => extractRateLimitEndpoint,
44527
44463
  extractXmtpSentAtMs: () => extractXmtpSentAtMs2,
44528
- fanOutSubscriptionJobs: () => fanOutSubscriptionJobs,
44529
44464
  findWindowsNativeOkxA2aExe: () => findWindowsNativeOkxA2aExe,
44530
44465
  followFile: () => followFile,
44531
44466
  formatDoctorReportForHumans: () => formatDoctorReportForHumans,
@@ -44538,7 +44473,6 @@ __export(index_exports, {
44538
44473
  getXmtpCreationCooldown: () => getXmtpCreationCooldown,
44539
44474
  handleCapabilitiesCommand: () => handleCapabilitiesCommand,
44540
44475
  handleDoctorCommand: () => handleDoctorCommand,
44541
- handleSubscriptionPushCommand: () => handleSubscriptionPushCommand,
44542
44476
  handleXmtpDebugCommand: () => handleXmtpDebugCommand,
44543
44477
  handleXmtpSendCommand: () => handleXmtpSendCommand,
44544
44478
  handleXmtpTestCommand: () => handleXmtpTestCommand,
@@ -44553,7 +44487,6 @@ __export(index_exports, {
44553
44487
  invalidateResolvedOnchainosBinForTests: () => invalidateResolvedOnchainosBinForTests,
44554
44488
  isAutostartManagerUnavailableError: () => isAutostartManagerUnavailableError,
44555
44489
  isDefaultTaskHome: () => isDefaultTaskHome,
44556
- isFingerprintKey: () => isFingerprintKey,
44557
44490
  isGatewayAvailableForHeartbeat: () => isGatewayAvailableForHeartbeat,
44558
44491
  isHermesGatewayPluginEnabled: () => isHermesGatewayPluginEnabled,
44559
44492
  isInfoEventAllowlisted: () => isInfoEventAllowlisted,
@@ -44564,7 +44497,6 @@ __export(index_exports, {
44564
44497
  isPrereleaseVersion: () => isPrereleaseVersion,
44565
44498
  isRetryableOpenClawGatewayError: () => isRetryableOpenClawGatewayError,
44566
44499
  isSqliteBusyError: () => isSqliteBusyError,
44567
- isSubscriptionEnvelope: () => isSubscriptionEnvelope,
44568
44500
  isSystemdManagerUnavailableMessage: () => isSystemdManagerUnavailableMessage,
44569
44501
  isTagKey: () => isTagKey,
44570
44502
  isValidExternalJobId: () => isValidExternalJobId,
@@ -44573,12 +44505,8 @@ __export(index_exports, {
44573
44505
  killProcessTree: () => killProcessTree,
44574
44506
  launchdPlistHasCurrentRestartPolicy: () => launchdPlistHasCurrentRestartPolicy,
44575
44507
  listAllAgentsWithMetadata: () => listAllAgentsWithMetadata,
44576
- listJobsByVerifiedSender: () => listJobsByVerifiedSender,
44577
- listJobsByVerifiedSenderHelpAdvertisesCommand: () => listJobsByVerifiedSenderHelpAdvertisesCommand,
44578
- listJobsByVerifiedSenderWithCapability: () => listJobsByVerifiedSenderWithCapability,
44579
44508
  logWinCompat: () => logWinCompat,
44580
44509
  logXmtpMessageSent: () => logXmtpMessageSent,
44581
- logger: () => logger,
44582
44510
  maybeRecommendOnchainosUpgrade: () => maybeRecommendOnchainosUpgrade,
44583
44511
  mergeA2AEnvelopeTips: () => mergeA2AEnvelopeTips,
44584
44512
  messageEligibleHelpAdvertisesOfflineReplay: () => messageEligibleHelpAdvertisesOfflineReplay,
@@ -44586,8 +44514,6 @@ __export(index_exports, {
44586
44514
  normalizeAiProvider: () => normalizeAiProvider,
44587
44515
  normalizeAiRuntimeProvider: () => normalizeAiRuntimeProvider,
44588
44516
  normalizeHermesOkxA2aPluginConfig: () => normalizeHermesOkxA2aPluginConfig,
44589
- normalizeListJobsResponse: () => normalizeListJobsResponse,
44590
- normalizeSubscriptionJobs: () => normalizeSubscriptionJobs,
44591
44517
  notifyAgentMessageToUserAttention: () => notifyAgentMessageToUserAttention,
44592
44518
  notifyDirectToUserAttention: () => notifyDirectToUserAttention,
44593
44519
  notifySystemMessageToUser: () => notifySystemMessageToUser,
@@ -44598,7 +44524,6 @@ __export(index_exports, {
44598
44524
  parsePluginYamlVersion: () => parsePluginYamlVersion,
44599
44525
  parseWalletLoginStatus: () => parseWalletLoginStatus,
44600
44526
  parseWindowsParentProcessJson: () => parseWindowsParentProcessJson,
44601
- partitionSubscriptionJobsByOwner: () => partitionSubscriptionJobsByOwner,
44602
44527
  performRuntimeSwitch: () => performRuntimeSwitch,
44603
44528
  persistAiRuntimeSurfaceBestEffort: () => persistAiRuntimeSurfaceBestEffort,
44604
44529
  persistCurrentRuntimeSelectionForNewJob: () => persistCurrentRuntimeSelectionForNewJob,
@@ -44608,14 +44533,12 @@ __export(index_exports, {
44608
44533
  printXmtpTestUsage: () => printXmtpTestUsage,
44609
44534
  probeCodexAuthStatus: () => probeCodexAuthStatus,
44610
44535
  processFileMessage: () => processFileMessage,
44611
- processSubscriptionInbound: () => processSubscriptionInbound,
44612
44536
  queryWalletLoginStatus: () => queryWalletLoginStatus,
44613
44537
  readAiProviderTimeoutMs: () => readAiProviderTimeoutMs,
44614
44538
  readAiRuntimeSurfaceBestEffort: () => readAiRuntimeSurfaceBestEffort,
44615
44539
  readCachedCodexReadiness: () => readCachedCodexReadiness,
44616
44540
  readLastLines: () => readLastLines,
44617
44541
  readParentProcessCommandForPlatform: () => readParentProcessCommandForPlatform,
44618
- readSubscriptionEnvelope: () => readSubscriptionEnvelope,
44619
44542
  readUserAttentionWatcherEvent: () => readUserAttentionWatcherEvent,
44620
44543
  refreshAgentsAndWait: () => refreshAgentsAndWait,
44621
44544
  refreshOnchainosVersionMetadata: () => refreshOnchainosVersionMetadata,
@@ -44626,10 +44549,8 @@ __export(index_exports, {
44626
44549
  replayScanBackoffWithJitterMs: () => replayScanBackoffWithJitterMs,
44627
44550
  reportDoctorRunToSentry: () => reportDoctorRunToSentry,
44628
44551
  reportUserNotificationFailure: () => reportUserNotificationFailure,
44629
- resetListJobsByVerifiedSenderCapabilityForTests: () => resetListJobsByVerifiedSenderCapabilityForTests,
44630
44552
  resetMessageEligibleOfflineReplayCapabilityForTests: () => resetMessageEligibleOfflineReplayCapabilityForTests,
44631
44553
  resetResolvedOnchainosBinForTests: () => resetResolvedOnchainosBinForTests,
44632
- resetSubscriptionTargetsForTests: () => resetSubscriptionTargetsForTests,
44633
44554
  resetXmtpCreationCooldownForTests: () => resetXmtpCreationCooldownForTests,
44634
44555
  resolveAiPermissionPreset: () => resolveAiPermissionPreset,
44635
44556
  resolveAiProviderCommand: () => resolveAiProviderCommand,
@@ -44683,8 +44604,6 @@ __export(index_exports, {
44683
44604
  stopOpenClawGateway: () => stopOpenClawGateway,
44684
44605
  stopSystemdAutostart: () => stopSystemdAutostart,
44685
44606
  subscribeUserAttentionEvents: () => subscribeUserAttentionEvents,
44686
- subscriptionIdempotencyKey: () => subscriptionIdempotencyKey,
44687
- summarizeSubscriptionPush: () => summarizeSubscriptionPush,
44688
44607
  summarizeXmtpTestEvents: () => summarizeXmtpTestEvents,
44689
44608
  switchProvider: () => switchProvider,
44690
44609
  switchProviderWithReadinessGate: () => switchProviderWithReadinessGate,
@@ -44693,7 +44612,6 @@ __export(index_exports, {
44693
44612
  tailFile: () => tailFile,
44694
44613
  toOpenClawGatewaySessionKey: () => toOpenClawGatewaySessionKey,
44695
44614
  toWindowsInvocation: () => toWindowsInvocation,
44696
- tryMarkSubscriptionTarget: () => tryMarkSubscriptionTarget,
44697
44615
  writeAiPermissionPresetToConfig: () => writeAiPermissionPresetToConfig
44698
44616
  });
44699
44617
  module.exports = __toCommonJS(index_exports);
@@ -44703,62 +44621,12 @@ init_autostart();
44703
44621
 
44704
44622
  // src/ai-runner.ts
44705
44623
  init_log();
44706
- var import_node_crypto5 = require("node:crypto");
44624
+ var import_node_crypto4 = require("node:crypto");
44707
44625
  var import_node_fs11 = require("node:fs");
44708
44626
  var import_promises7 = require("node:fs/promises");
44709
44627
  var import_node_os6 = require("node:os");
44710
44628
  var import_node_path16 = require("node:path");
44711
44629
  init_ai_command();
44712
-
44713
- // src/ai-run-log-path.ts
44714
- var import_node_crypto2 = require("node:crypto");
44715
- var RUN_LOG_FILENAME_MAX_BYTES = 240;
44716
- function buildRunLogFileName(request) {
44717
- const source = request.source;
44718
- const sessionKey = request.sessionKey;
44719
- const messageId = request.messageId;
44720
- const jobId = request.jobId;
44721
- const safeMessageId = encodeURIComponent(messageId);
44722
- const prefix = source === "job-dispatch" ? "ai-" : "ai-session-";
44723
- const encodedContext = source === "job-dispatch" ? encodeURIComponent(jobId ?? "unknown") : encodeURIComponent(sessionKey);
44724
- const readable = `${prefix}${encodedContext}-${safeMessageId}.log`;
44725
- if (Buffer.byteLength(readable, "utf8") <= RUN_LOG_FILENAME_MAX_BYTES) {
44726
- return readable;
44727
- }
44728
- const readableWithoutExt = readable.slice(0, -".log".length);
44729
- const digest = (0, import_node_crypto2.createHash)("sha256").update(readableWithoutExt).digest("hex").slice(0, 24);
44730
- const suffix = `-${digest}.log`;
44731
- const budgetForContext = RUN_LOG_FILENAME_MAX_BYTES - Buffer.byteLength(prefix, "utf8") - Buffer.byteLength(suffix, "utf8");
44732
- const contextHead = truncateToUtf8ByteBudgetSafe(encodedContext, Math.max(budgetForContext, 0));
44733
- return `${prefix}${contextHead}${suffix}`;
44734
- }
44735
- function truncateToUtf8ByteBudgetSafe(encoded, maxBytes) {
44736
- if (maxBytes <= 0) {
44737
- return "";
44738
- }
44739
- if (Buffer.byteLength(encoded, "utf8") <= maxBytes) {
44740
- return encoded;
44741
- }
44742
- let candidateLength = Math.min(maxBytes, encoded.length);
44743
- while (candidateLength > 0) {
44744
- const candidate = encoded.slice(0, candidateLength);
44745
- if (!endsWithSplitEscape(candidate)) {
44746
- return candidate;
44747
- }
44748
- candidateLength -= 1;
44749
- }
44750
- return "";
44751
- }
44752
- function endsWithSplitEscape(value) {
44753
- const percentIndex = value.lastIndexOf("%");
44754
- if (percentIndex === -1) {
44755
- return false;
44756
- }
44757
- const tail = value.length - percentIndex - 1;
44758
- return tail < 2;
44759
- }
44760
-
44761
- // src/ai-runner.ts
44762
44630
  init_paths();
44763
44631
 
44764
44632
  // src/file-store.ts
@@ -46439,15 +46307,13 @@ var AiRunner = class {
46439
46307
  );
46440
46308
  }
46441
46309
  buildRunLogPath(request) {
46442
- return (0, import_node_path16.join)(
46443
- this.logsDir,
46444
- buildRunLogFileName({
46445
- source: request.source,
46446
- sessionKey: request.sessionKey,
46447
- messageId: request.messageId,
46448
- jobId: request.jobId
46449
- })
46450
- );
46310
+ const safeMessageId = encodeURIComponent(request.messageId);
46311
+ if (request.source === "job-dispatch") {
46312
+ const safeJobId = encodeURIComponent(request.jobId ?? "unknown");
46313
+ return (0, import_node_path16.join)(this.logsDir, `ai-${safeJobId}-${safeMessageId}.log`);
46314
+ }
46315
+ const safeSessionKey = encodeURIComponent(request.sessionKey);
46316
+ return (0, import_node_path16.join)(this.logsDir, `ai-session-${safeSessionKey}-${safeMessageId}.log`);
46451
46317
  }
46452
46318
  readRunAiSessionId(provider, request, file, sessionMeta) {
46453
46319
  if (request.source === "job-dispatch" && request.jobId) {
@@ -48169,7 +48035,7 @@ function normalizeAttentionProvider(provider) {
48169
48035
  return provider === "unknown" ? null : provider;
48170
48036
  }
48171
48037
  function stableHash(value) {
48172
- return (0, import_node_crypto5.createHash)("sha256").update(value).digest("hex").slice(0, 24);
48038
+ return (0, import_node_crypto4.createHash)("sha256").update(value).digest("hex").slice(0, 24);
48173
48039
  }
48174
48040
  function formatCommand(args) {
48175
48041
  return args.map(shellQuote).join(" ");
@@ -48196,11 +48062,10 @@ function shortenJobId(jobId) {
48196
48062
 
48197
48063
  // src/command-store.ts
48198
48064
  init_log();
48199
- var import_node_crypto6 = require("node:crypto");
48065
+ var import_node_crypto5 = require("node:crypto");
48200
48066
  var import_node_fs12 = require("node:fs");
48201
48067
  var import_node_path17 = require("node:path");
48202
48068
  init_paths();
48203
- init_session_store();
48204
48069
  var { DatabaseSync: DatabaseSync2 } = loadSqlite2();
48205
48070
  var XMTP_DEBUG_RESULT_TTL_MS = 5 * 6e4;
48206
48071
  function stringifyForStorage(value) {
@@ -48222,7 +48087,7 @@ var CommandStore = class {
48222
48087
  }
48223
48088
  createXmtpSendCommand(params) {
48224
48089
  return {
48225
- id: (0, import_node_crypto6.randomUUID)(),
48090
+ id: (0, import_node_crypto5.randomUUID)(),
48226
48091
  type: "xmtp-send",
48227
48092
  jobId: params.jobId,
48228
48093
  message: params.message,
@@ -48236,27 +48101,16 @@ var CommandStore = class {
48236
48101
  createdAt: Date.now()
48237
48102
  };
48238
48103
  }
48239
- createXmtpSubscriptionPushCommand(params) {
48240
- return {
48241
- id: (0, import_node_crypto6.randomUUID)(),
48242
- type: "xmtp-subscription-push",
48243
- myAgentId: params.myAgentId,
48244
- content: params.content,
48245
- conversationIds: params.conversationIds,
48246
- deliveryId: params.deliveryId,
48247
- createdAt: Date.now()
48248
- };
48249
- }
48250
48104
  createXmtpGetPendingListCommand() {
48251
48105
  return {
48252
- id: (0, import_node_crypto6.randomUUID)(),
48106
+ id: (0, import_node_crypto5.randomUUID)(),
48253
48107
  type: "xmtp-get-pending-list",
48254
48108
  createdAt: Date.now()
48255
48109
  };
48256
48110
  }
48257
48111
  createXmtpDenyPendingConversationCommand(params) {
48258
48112
  return {
48259
- id: (0, import_node_crypto6.randomUUID)(),
48113
+ id: (0, import_node_crypto5.randomUUID)(),
48260
48114
  type: "xmtp-deny-pending-conversation",
48261
48115
  groupId: params.groupId,
48262
48116
  jobId: params.jobId,
@@ -48267,14 +48121,14 @@ var CommandStore = class {
48267
48121
  }
48268
48122
  createXmtpRefreshAgentsCommand() {
48269
48123
  return {
48270
- id: (0, import_node_crypto6.randomUUID)(),
48124
+ id: (0, import_node_crypto5.randomUUID)(),
48271
48125
  type: "xmtp-refresh-agents",
48272
48126
  createdAt: Date.now()
48273
48127
  };
48274
48128
  }
48275
48129
  createXmtpGetConversationHistoryCommand(params) {
48276
48130
  return {
48277
- id: (0, import_node_crypto6.randomUUID)(),
48131
+ id: (0, import_node_crypto5.randomUUID)(),
48278
48132
  type: "xmtp-get-conversation-history",
48279
48133
  jobId: params.jobId,
48280
48134
  toAgentId: params.toAgentId,
@@ -48286,7 +48140,7 @@ var CommandStore = class {
48286
48140
  }
48287
48141
  createXmtpDebugCommand(params) {
48288
48142
  return {
48289
- id: (0, import_node_crypto6.randomUUID)(),
48143
+ id: (0, import_node_crypto5.randomUUID)(),
48290
48144
  type: "xmtp-debug",
48291
48145
  action: params.action,
48292
48146
  groupId: params.groupId,
@@ -48301,7 +48155,7 @@ var CommandStore = class {
48301
48155
  }
48302
48156
  createAiJobMessageDispatchCommand(params) {
48303
48157
  return {
48304
- id: (0, import_node_crypto6.randomUUID)(),
48158
+ id: (0, import_node_crypto5.randomUUID)(),
48305
48159
  type: "ai-dispatch",
48306
48160
  kind: "job-message",
48307
48161
  jobId: params.jobId,
@@ -48312,7 +48166,7 @@ var CommandStore = class {
48312
48166
  }
48313
48167
  createAiSessionMessageDispatchCommand(params) {
48314
48168
  return {
48315
- id: (0, import_node_crypto6.randomUUID)(),
48169
+ id: (0, import_node_crypto5.randomUUID)(),
48316
48170
  type: "ai-dispatch",
48317
48171
  kind: "session-message",
48318
48172
  sessionKey: params.sessionKey,
@@ -48340,65 +48194,6 @@ var CommandStore = class {
48340
48194
  );
48341
48195
  return this.commandPath(command.id);
48342
48196
  }
48343
- /**
48344
- * Atomic idempotent submit keyed on a business `idempotencyKey` (DEXMARKET-9035,
48345
- * M2). The FIRST caller for a given key inserts its command and gets
48346
- * `created: true`; every later caller with the SAME key — including after a
48347
- * daemon / CommandStore rebuild — gets the ALREADY-persisted command back with
48348
- * `created: false` and NO new row. Concurrency-safe: correctness rests on the
48349
- * partial UNIQUE index on `idempotency_key`, not a check-then-insert (which
48350
- * races), so a `INSERT ... ON CONFLICT DO NOTHING` collapses concurrent
48351
- * duplicates to exactly one row. Recoverable SQLITE_BUSY/LOCKED errors reuse
48352
- * the repo's bounded exponential backoff. This never changes the plain
48353
- * `submit` path used by `xmtp-send` and every other daemon command.
48354
- */
48355
- async submitIdempotent(command, idempotencyKey) {
48356
- if (!idempotencyKey) {
48357
- throw new Error("submitIdempotent requires a non-empty idempotencyKey");
48358
- }
48359
- return this.withBusyRetry(
48360
- () => this.transaction(() => {
48361
- const now = Date.now();
48362
- const insert = this.db.prepare(`
48363
- INSERT INTO command_queue (
48364
- id, type, status, command_json, result_json,
48365
- created_at_ms, updated_at_ms, processing_started_at_ms, completed_at_ms,
48366
- idempotency_key
48367
- )
48368
- VALUES (?, ?, 'pending', ?, NULL, ?, ?, NULL, NULL, ?)
48369
- ON CONFLICT(idempotency_key) WHERE idempotency_key IS NOT NULL DO NOTHING
48370
- `).run(
48371
- command.id,
48372
- command.type,
48373
- stringifyForStorage(command),
48374
- normalizeCreatedAt(command.createdAt, now),
48375
- now,
48376
- idempotencyKey
48377
- );
48378
- if (Number(insert.changes ?? 0) > 0) {
48379
- return { path: this.commandPath(command.id), commandId: command.id, created: true };
48380
- }
48381
- const existing = this.db.prepare(`
48382
- SELECT id FROM command_queue WHERE idempotency_key = ?
48383
- `).get(idempotencyKey);
48384
- const existingId = existing?.id ?? command.id;
48385
- return { path: this.commandPath(existingId), commandId: existingId, created: false };
48386
- })
48387
- );
48388
- }
48389
- async withBusyRetry(operation) {
48390
- const attempts = 6;
48391
- for (let attempt = 1; ; attempt += 1) {
48392
- try {
48393
- return operation();
48394
- } catch (err) {
48395
- if (!isSqliteBusyError(err) || attempt >= attempts) {
48396
- throw err;
48397
- }
48398
- await new Promise((resolve11) => setTimeout(resolve11, Math.min(50 * 2 ** (attempt - 1), 1e3)));
48399
- }
48400
- }
48401
- }
48402
48197
  async listPending() {
48403
48198
  return (await this.listPendingEntries()).map((entry) => entry.command);
48404
48199
  }
@@ -48465,24 +48260,9 @@ var CommandStore = class {
48465
48260
  CREATE INDEX IF NOT EXISTS idx_command_queue_status_created
48466
48261
  ON command_queue(status, created_at_ms, id)
48467
48262
  `);
48468
- this.ensureColumn("command_queue", "idempotency_key", "TEXT");
48469
- this.db.exec(`
48470
- CREATE UNIQUE INDEX IF NOT EXISTS idx_command_queue_idempotency_key
48471
- ON command_queue(idempotency_key)
48472
- WHERE idempotency_key IS NOT NULL
48473
- `);
48474
48263
  this.purgeExpiredXmtpDebugResults();
48475
48264
  this.importLegacyFileCommands();
48476
48265
  }
48477
- ensureColumn(table, column, definition) {
48478
- this.transaction(() => {
48479
- const rows = this.db.prepare(`PRAGMA table_info(${table})`).all();
48480
- if (rows.some((row) => row.name === column)) {
48481
- return;
48482
- }
48483
- this.db.exec(`ALTER TABLE ${table} ADD COLUMN ${column} ${definition}`);
48484
- });
48485
- }
48486
48266
  purgeExpiredXmtpDebugResults() {
48487
48267
  this.db.prepare(`
48488
48268
  DELETE FROM command_queue
@@ -48654,10 +48434,6 @@ function isDaemonCommand(value) {
48654
48434
  if (parsed.type === "xmtp-send") {
48655
48435
  return typeof parsed.jobId === "string" && typeof parsed.message === "string";
48656
48436
  }
48657
- if (parsed.type === "xmtp-subscription-push") {
48658
- const command = parsed;
48659
- return typeof command.myAgentId === "string" && typeof command.content === "string" && Array.isArray(command.conversationIds) && command.conversationIds.every((item) => typeof item === "string");
48660
- }
48661
48437
  if (parsed.type === "xmtp-get-pending-list") {
48662
48438
  return true;
48663
48439
  }
@@ -48824,7 +48600,7 @@ var import_node_path21 = require("node:path");
48824
48600
  // ../../node_modules/@xmtp/node-sdk/dist/index.js
48825
48601
  var import_node_bindings = require("@xmtp/node-bindings");
48826
48602
  var import_node_bindings2 = require("@xmtp/node-bindings");
48827
- var import_node_crypto7 = require("node:crypto");
48603
+ var import_node_crypto6 = require("node:crypto");
48828
48604
 
48829
48605
  // ../../node_modules/@xmtp/node-sdk/node_modules/@xmtp/content-type-primitives/dist/index.js
48830
48606
  var contentTypeToString = (contentType) => `${contentType.authorityId}/${contentType.typeId}:${contentType.versionMajor}.${contentType.versionMinor}`;
@@ -49267,7 +49043,6 @@ function createAsyncStreamProxy(stream) {
49267
49043
  }
49268
49044
  });
49269
49045
  }
49270
- var wait = (ms) => new Promise((resolve11) => setTimeout(resolve11, ms));
49271
49046
  var DEFAULT_RETRY_DELAY = 6e4;
49272
49047
  var DEFAULT_RETRY_ATTEMPTS = 10;
49273
49048
  var createStream = async (streamFunction, streamValueMutator, options) => {
@@ -49276,82 +49051,161 @@ var createStream = async (streamFunction, streamValueMutator, options) => {
49276
49051
  throw new StreamInvalidRetryAttemptsError();
49277
49052
  }
49278
49053
  const asyncStream = new AsyncStream();
49054
+ let stopped = false;
49055
+ let current;
49056
+ let recovering = false;
49057
+ let cancelDelay;
49058
+ const isStopped = () => stopped;
49059
+ const isCurrent = (native) => !stopped && current === native;
49060
+ asyncStream.onDone = () => {
49061
+ if (stopped) {
49062
+ return;
49063
+ }
49064
+ stopped = true;
49065
+ cancelDelay?.();
49066
+ const native = current;
49067
+ current = void 0;
49068
+ native?.closer?.end();
49069
+ };
49070
+ const delay = (ms) => new Promise((resolve11) => {
49071
+ const timer = setTimeout(() => {
49072
+ cancelDelay = void 0;
49073
+ resolve11();
49074
+ }, ms);
49075
+ cancelDelay = () => {
49076
+ clearTimeout(timer);
49077
+ cancelDelay = void 0;
49078
+ resolve11();
49079
+ };
49080
+ });
49081
+ const reportError = (error) => {
49082
+ if (!stopped) {
49083
+ onError?.(error);
49084
+ }
49085
+ };
49086
+ const deliver = (value) => {
49087
+ if (stopped || value === void 0) {
49088
+ return;
49089
+ }
49090
+ asyncStream.push(value);
49091
+ onValue?.(value);
49092
+ };
49279
49093
  const streamCallback = (error, value) => {
49094
+ if (stopped) {
49095
+ return;
49096
+ }
49280
49097
  if (error) {
49281
49098
  onError?.(error);
49282
49099
  return;
49283
49100
  }
49284
- if (value !== void 0) {
49285
- try {
49286
- if (streamValueMutator) {
49287
- const mutatedValue = streamValueMutator(value);
49288
- if ((0, import_types.isPromise)(mutatedValue)) {
49289
- void mutatedValue.then((mutatedValue2) => {
49290
- if (mutatedValue2 !== void 0) {
49291
- asyncStream.push(mutatedValue2);
49292
- onValue?.(mutatedValue2);
49293
- }
49294
- }).catch((error2) => {
49295
- onError?.(error2);
49296
- });
49297
- } else {
49298
- if (mutatedValue !== void 0) {
49299
- asyncStream.push(mutatedValue);
49300
- onValue?.(mutatedValue);
49301
- }
49302
- }
49101
+ if (value === void 0) {
49102
+ return;
49103
+ }
49104
+ try {
49105
+ if (streamValueMutator) {
49106
+ const mutatedValue = streamValueMutator(value);
49107
+ if ((0, import_types.isPromise)(mutatedValue)) {
49108
+ void mutatedValue.then(deliver).catch(reportError);
49303
49109
  } else {
49304
- asyncStream.push(value);
49305
- onValue?.(value);
49110
+ deliver(mutatedValue);
49306
49111
  }
49307
- } catch (error2) {
49308
- onError?.(error2);
49112
+ } else {
49113
+ deliver(value);
49309
49114
  }
49115
+ } catch (error2) {
49116
+ reportError(error2);
49310
49117
  }
49311
49118
  };
49312
- const retry2 = async (retries = retryAttempts) => {
49313
- if (retries === 0) {
49314
- void asyncStream.end();
49315
- onError?.(new StreamFailedError(retryAttempts));
49316
- return;
49119
+ const fail = (error) => {
49120
+ void asyncStream.end();
49121
+ onError?.(error);
49122
+ };
49123
+ const open2 = async () => {
49124
+ if (stopped) {
49125
+ return false;
49126
+ }
49127
+ const native = { ready: false, closed: false };
49128
+ current = native;
49129
+ const closer = await streamFunction(streamCallback, () => {
49130
+ onNativeClose(native);
49131
+ });
49132
+ native.closer = closer;
49133
+ if (!isCurrent(native)) {
49134
+ closer.end();
49135
+ return false;
49136
+ }
49137
+ await closer.waitForReady();
49138
+ if (!isCurrent(native)) {
49139
+ closer.end();
49140
+ return false;
49141
+ }
49142
+ if (native.closed || closer.isClosed()) {
49143
+ closer.end();
49144
+ return false;
49317
49145
  }
49318
- await wait(retryDelay);
49319
- onRetry?.(retryAttempts - retries + 1, retryAttempts);
49146
+ native.ready = true;
49147
+ return true;
49148
+ };
49149
+ const restart = async () => {
49320
49150
  try {
49321
- const streamCloser = await streamFunction(streamCallback, () => {
49322
- onFail?.();
49323
- void retry2();
49324
- });
49325
- await streamCloser.waitForReady();
49326
- asyncStream.onDone = () => {
49327
- streamCloser.end();
49328
- };
49329
- onRestart?.();
49330
- } catch (error) {
49331
- onError?.(error);
49332
- void retry2(retries - 1);
49151
+ for (let attempt = 1; attempt <= retryAttempts; attempt++) {
49152
+ await delay(retryDelay);
49153
+ if (isStopped()) {
49154
+ return;
49155
+ }
49156
+ onRetry?.(attempt, retryAttempts);
49157
+ let restarted = false;
49158
+ try {
49159
+ restarted = await open2();
49160
+ } catch (error) {
49161
+ reportError(error);
49162
+ }
49163
+ if (isStopped()) {
49164
+ return;
49165
+ }
49166
+ if (restarted) {
49167
+ try {
49168
+ onRestart?.();
49169
+ } catch (error) {
49170
+ reportError(error);
49171
+ }
49172
+ return;
49173
+ }
49174
+ }
49175
+ fail(new StreamFailedError(retryAttempts));
49176
+ } finally {
49177
+ recovering = false;
49333
49178
  }
49334
49179
  };
49335
- const startRetry = () => {
49336
- if (retryOnFail) {
49337
- void retry2();
49338
- } else {
49339
- void asyncStream.end();
49340
- onError?.(new StreamFailedError(0));
49180
+ const recover = () => {
49181
+ if (stopped || recovering) {
49182
+ return;
49183
+ }
49184
+ if (!retryOnFail) {
49185
+ fail(new StreamFailedError(0));
49186
+ return;
49341
49187
  }
49188
+ recovering = true;
49189
+ void restart();
49342
49190
  };
49191
+ function onNativeClose(native) {
49192
+ if (!isCurrent(native) || native.closed) {
49193
+ return;
49194
+ }
49195
+ native.closed = true;
49196
+ onFail?.();
49197
+ if (native.ready) {
49198
+ recover();
49199
+ }
49200
+ }
49201
+ let started = false;
49343
49202
  try {
49344
- const streamCloser = await streamFunction(streamCallback, () => {
49345
- onFail?.();
49346
- startRetry();
49347
- });
49348
- await streamCloser.waitForReady();
49349
- asyncStream.onDone = () => {
49350
- streamCloser.end();
49351
- };
49203
+ started = await open2();
49352
49204
  } catch (error) {
49353
- onError?.(error);
49354
- startRetry();
49205
+ reportError(error);
49206
+ }
49207
+ if (!started) {
49208
+ recover();
49355
49209
  }
49356
49210
  return createAsyncStreamProxy(asyncStream);
49357
49211
  };
@@ -50546,7 +50400,7 @@ var resolveBackend = async (envOrBackend, gatewayHost) => {
50546
50400
  return createBackend({ env: envOrBackend, gatewayHost });
50547
50401
  };
50548
50402
  var createEphemeralIdentifier = () => ({
50549
- identifier: `0x${(0, import_node_crypto7.randomBytes)(20).toString("hex")}`,
50403
+ identifier: `0x${(0, import_node_crypto6.randomBytes)(20).toString("hex")}`,
50550
50404
  identifierKind: 0
50551
50405
  });
50552
50406
  var toInboxUpdatesCountMap = (value) => {
@@ -52595,7 +52449,7 @@ function observe(observerId, callbacks, fn) {
52595
52449
  }
52596
52450
 
52597
52451
  // ../../node_modules/viem/_esm/utils/wait.js
52598
- async function wait2(time) {
52452
+ async function wait(time) {
52599
52453
  return new Promise((res) => setTimeout(res, time));
52600
52454
  }
52601
52455
 
@@ -52608,12 +52462,12 @@ function poll(fn, { emitOnBegin, initialWaitTime, interval }) {
52608
52462
  if (emitOnBegin)
52609
52463
  data = await fn({ unpoll: unwatch });
52610
52464
  const initialWait = await initialWaitTime?.(data) ?? interval;
52611
- await wait2(initialWait);
52465
+ await wait(initialWait);
52612
52466
  const poll2 = async () => {
52613
52467
  if (!active)
52614
52468
  return;
52615
52469
  await fn({ unpoll: unwatch });
52616
- await wait2(interval);
52470
+ await wait(interval);
52617
52471
  poll2();
52618
52472
  };
52619
52473
  poll2();
@@ -52936,7 +52790,7 @@ function withRetry(fn, { delay: delay_ = 100, retryCount = 2, shouldRetry: shoul
52936
52790
  const retry2 = async ({ error }) => {
52937
52791
  const delay = typeof delay_ === "function" ? delay_({ count, error }) : delay_;
52938
52792
  if (delay)
52939
- await wait2(delay);
52793
+ await wait(delay);
52940
52794
  attemptRetry({ count: count + 1 });
52941
52795
  };
52942
52796
  try {
@@ -55099,7 +54953,7 @@ init_createBatchScheduler();
55099
54953
  function http(url, config = {}) {
55100
54954
  const { batch, fetchFn, fetchOptions, key = "http", methods, name = "HTTP JSON-RPC", onFetchRequest, onFetchResponse, retryDelay, raw } = config;
55101
54955
  return ({ chain, retryCount: retryCount_, timeout: timeout_ }) => {
55102
- const { batchSize = 1e3, wait: wait3 = 0 } = typeof batch === "object" ? batch : {};
54956
+ const { batchSize = 1e3, wait: wait2 = 0 } = typeof batch === "object" ? batch : {};
55103
54957
  const retryCount = config.retryCount ?? retryCount_;
55104
54958
  const timeout = timeout_ ?? config.timeout ?? 1e4;
55105
54959
  const url_ = url || chain?.rpcUrls.default.http[0];
@@ -55120,7 +54974,7 @@ function http(url, config = {}) {
55120
54974
  const body = { method, params };
55121
54975
  const { schedule } = createBatchScheduler({
55122
54976
  id: url_,
55123
- wait: wait3,
54977
+ wait: wait2,
55124
54978
  shouldSplitBatch(requests) {
55125
54979
  return requests.length > batchSize;
55126
54980
  },
@@ -55336,8 +55190,8 @@ var sepolia = /* @__PURE__ */ defineChain({
55336
55190
  });
55337
55191
 
55338
55192
  // ../../node_modules/@xmtp/agent-sdk/dist/index.js
55339
- var import_node_crypto8 = require("node:crypto");
55340
- var version2 = "2.3.0";
55193
+ var import_node_crypto7 = require("node:crypto");
55194
+ var version2 = "2.3.1";
55341
55195
  var fromSelf = (message, client) => {
55342
55196
  return message.senderInboxId === client.inboxId;
55343
55197
  };
@@ -56031,7 +55885,7 @@ var Agent = class _Agent extends import_node_events.default {
56031
55885
  return this.#client.accountIdentifier?.identifier;
56032
55886
  }
56033
55887
  };
56034
- var CANCEL_ACTION_ID = (0, import_node_crypto8.randomUUID)();
55888
+ var CANCEL_ACTION_ID = (0, import_node_crypto7.randomUUID)();
56035
55889
  var LimitedMap = class {
56036
55890
  #map = /* @__PURE__ */ new Map();
56037
55891
  #limit;
@@ -57386,6 +57240,9 @@ function replayScanBackoffWithJitterMs(consecutiveFailures, randomValue = Math.r
57386
57240
  const jitteredMs = Math.round(baseMs * (0.9 + boundedRandom * 0.2));
57387
57241
  return Math.min(REPLAY_SCAN_MAX_BACKOFF_MS, jitteredMs);
57388
57242
  }
57243
+ function isListenHealthy(outcome) {
57244
+ return outcome === "started" || outcome === "retrying";
57245
+ }
57389
57246
  function isOfflineReplayForTrigger(trigger) {
57390
57247
  return trigger === "startup";
57391
57248
  }
@@ -57395,6 +57252,18 @@ function replaySingleFlightDiscriminator(trigger, clientGeneration) {
57395
57252
  isOfflineReplayForTrigger(trigger)
57396
57253
  );
57397
57254
  }
57255
+ var XmtpClientCreateBlockedError = class extends Error {
57256
+ reason;
57257
+ address;
57258
+ agentId;
57259
+ constructor(reason, address, agentId) {
57260
+ super(`xmtp client create blocked (${reason})`);
57261
+ this.name = "XmtpClientCreateBlockedError";
57262
+ this.reason = reason;
57263
+ this.address = address;
57264
+ this.agentId = agentId;
57265
+ }
57266
+ };
57398
57267
  var XmtpService = class _XmtpService {
57399
57268
  static instance = null;
57400
57269
  env = process.env.XMTP_ENV ?? "production";
@@ -57432,6 +57301,25 @@ var XmtpService = class _XmtpService {
57432
57301
  streamRecoverySetTimeout = (callback, delayMs) => setTimeout(callback, delayMs);
57433
57302
  streamRecoveryClearTimeout = (timer) => clearTimeout(timer);
57434
57303
  streamStartSetTimeout = (callback, delayMs) => setTimeout(callback, delayMs);
57304
+ xmtpAgentFactory = createAgentWithInstallationPrune;
57305
+ // Old clients whose close() was not confirmed. Keyed by lower-cased address.
57306
+ // The reference is kept only for controlled cleanup; it is never served.
57307
+ pendingReleaseByAddress = /* @__PURE__ */ new Map();
57308
+ // Addresses whose pending release was confirmed late (after the caller gave
57309
+ // up waiting) and still need a replacement client on the next recycle.
57310
+ releaseConfirmedNeedsCreate = /* @__PURE__ */ new Set();
57311
+ // Lower-cased addresses owned by a create. The slot is held from before the
57312
+ // SDK factory runs until the new client is registered in `clients` (or the
57313
+ // create failed), so no flow can observe "no lock and no client".
57314
+ clientCreateInFlight = /* @__PURE__ */ new Set();
57315
+ // Clients whose close() was confirmed; a repeated release is a no-op.
57316
+ releasedClients = /* @__PURE__ */ new WeakSet();
57317
+ // One listener setup per client, shared by concurrent init/refresh callers.
57318
+ listenTaskByClient = /* @__PURE__ */ new WeakMap();
57319
+ inboundReplayGateOwners = /* @__PURE__ */ new WeakMap();
57320
+ releaseWaitTimeoutMs = 3e4;
57321
+ releaseWaitSetTimeout = (callback, delayMs) => setTimeout(callback, delayMs);
57322
+ releaseWaitClearTimeout = (timer) => clearTimeout(timer);
57435
57323
  nextClientGeneration = 1;
57436
57324
  clientGenerationByClient = /* @__PURE__ */ new WeakMap();
57437
57325
  resolveStartupReplayCompletion;
@@ -57580,6 +57468,56 @@ var XmtpService = class _XmtpService {
57580
57468
  return { ok: remaining.length === 0, failures: remaining };
57581
57469
  }
57582
57470
  async createClientForAgent(agentInfo, options = {}) {
57471
+ const address = agentInfo.communicationAddress;
57472
+ const addressKey = address.toLowerCase();
57473
+ let blockedReason;
57474
+ if (this.pendingReleaseByAddress.has(addressKey)) {
57475
+ blockedReason = "release_pending";
57476
+ } else if (this.clientCreateInFlight.has(addressKey)) {
57477
+ blockedReason = "create_in_flight";
57478
+ } else if (this.getClientByAddress(address)) {
57479
+ blockedReason = "client_active";
57480
+ }
57481
+ if (blockedReason) {
57482
+ throw new XmtpClientCreateBlockedError(
57483
+ blockedReason,
57484
+ address,
57485
+ agentInfo.agentId
57486
+ );
57487
+ }
57488
+ this.clientCreateInFlight.add(addressKey);
57489
+ try {
57490
+ const created = await this.createClientForAgentGuarded(agentInfo, options);
57491
+ await this.registerCreatedClient(created, options.logPrefix ?? "[xmtp-sdk]");
57492
+ return created;
57493
+ } finally {
57494
+ this.clientCreateInFlight.delete(addressKey);
57495
+ }
57496
+ }
57497
+ // Ownership hand-off, still inside the create slot: the new client becomes
57498
+ // visible in `clients` before the slot is released. Never overwrites an
57499
+ // existing registration; a conflicting new object is released, not dropped.
57500
+ async registerCreatedClient(created, phase) {
57501
+ const { address, agent, agentInfo } = created;
57502
+ const addressKey = address.toLowerCase();
57503
+ const existing = this.getClientByAddress(address);
57504
+ if (existing && existing !== agent || this.pendingReleaseByAddress.has(addressKey)) {
57505
+ const reason = existing ? "client_active" : "release_pending";
57506
+ logWithTimestamp(
57507
+ `[xmtp-sdk] create registration conflict (${reason}): ${address} (agentId=${agentInfo.agentId}), releasing the new client`
57508
+ );
57509
+ await this.releaseClient(
57510
+ address,
57511
+ agent,
57512
+ agentInfo.agentId,
57513
+ `${phase}/register-conflict`
57514
+ );
57515
+ throw new XmtpClientCreateBlockedError(reason, address, agentInfo.agentId);
57516
+ }
57517
+ this.stoppedAddresses.delete(addressKey);
57518
+ this.clients.set(address, agent);
57519
+ }
57520
+ async createClientForAgentGuarded(agentInfo, options = {}) {
57583
57521
  const address = agentInfo.communicationAddress;
57584
57522
  const phase = options.logPrefix ?? "[xmtp-sdk]";
57585
57523
  const cooldown = getXmtpCreationCooldown();
@@ -57608,7 +57546,7 @@ var XmtpService = class _XmtpService {
57608
57546
  try {
57609
57547
  const signer = this.tools.createSigner(agentInfo);
57610
57548
  const dbPath = (inboxId2) => `${this.dataDir}/${inboxId2}-${this.env}.db3`;
57611
- const agent = await createAgentWithInstallationPrune(signer, {
57549
+ const agent = await this.xmtpAgentFactory(signer, {
57612
57550
  dbPath,
57613
57551
  env: this.env
57614
57552
  }, {
@@ -57617,6 +57555,7 @@ var XmtpService = class _XmtpService {
57617
57555
  logPrefix: options.logPrefix
57618
57556
  });
57619
57557
  cooldown.recordCreateSuccess(decision);
57558
+ this.releaseConfirmedNeedsCreate.delete(address.toLowerCase());
57620
57559
  if (decision.mode === "probe") {
57621
57560
  logger.info(LogEvent.XMTP_RATE_LIMIT_RECOVERED, {
57622
57561
  onchainosAgentId: agentInfo.agentId,
@@ -57654,6 +57593,128 @@ var XmtpService = class _XmtpService {
57654
57593
  throw err;
57655
57594
  }
57656
57595
  }
57596
+ logReleaseNotConfirmed(address, agentId, phase, reason, err) {
57597
+ logger.error(
57598
+ LogEvent.XMTP_CLIENT_CLOSE_FAILED,
57599
+ err instanceof Error ? err : new Error(`xmtp client close not confirmed (${reason})`),
57600
+ { walletAddress: address, onchainosAgentId: agentId, phase, reason }
57601
+ );
57602
+ }
57603
+ // Single release entry (recycle / refresh remove / failed replacement).
57604
+ // Confirmation is ONLY a successful client.close(); a timeout, a missing
57605
+ // close() or a close failure keeps the old reference in
57606
+ // pendingReleaseByAddress and blocks new creates for that address.
57607
+ async releaseClient(address, client, agentId, phase) {
57608
+ const key = address.toLowerCase();
57609
+ if (this.releasedClients.has(client)) {
57610
+ this.unpublishClient(address, client, phase);
57611
+ return true;
57612
+ }
57613
+ const existing = this.pendingReleaseByAddress.get(key);
57614
+ if (existing?.inFlight) {
57615
+ this.unpublishClient(address, client, phase);
57616
+ return false;
57617
+ }
57618
+ const entry = existing ?? { client, agentId, phase };
57619
+ entry.client = client;
57620
+ entry.agentId = agentId;
57621
+ entry.phase = phase;
57622
+ this.pendingReleaseByAddress.set(key, entry);
57623
+ this.unpublishClient(address, client, phase);
57624
+ let timedOut = false;
57625
+ const task = stopAndCloseXmtpClient(client, {
57626
+ address,
57627
+ agentId,
57628
+ phase,
57629
+ onCloseError: (err) => this.logReleaseNotConfirmed(address, agentId, phase, "close_threw", err)
57630
+ }).then((result) => {
57631
+ if (!result.stopped) {
57632
+ logWithTimestamp(
57633
+ `[xmtp-sdk] release: stop failed but close proceeded: ${address} (agentId=${agentId}) phase=${phase}`
57634
+ );
57635
+ }
57636
+ entry.inFlight = void 0;
57637
+ if (result.closed) {
57638
+ this.releasedClients.add(client);
57639
+ }
57640
+ if (result.closed && this.pendingReleaseByAddress.get(key) === entry) {
57641
+ this.pendingReleaseByAddress.delete(key);
57642
+ if (timedOut) {
57643
+ this.releaseConfirmedNeedsCreate.add(key);
57644
+ }
57645
+ }
57646
+ return result;
57647
+ });
57648
+ entry.inFlight = task.then((result) => result.closed);
57649
+ const timeoutHandle = {};
57650
+ const timeoutPromise = new Promise((resolve11) => {
57651
+ timeoutHandle.timer = this.releaseWaitSetTimeout(
57652
+ () => resolve11(null),
57653
+ this.releaseWaitTimeoutMs
57654
+ );
57655
+ });
57656
+ const outcome = await Promise.race([task, timeoutPromise]);
57657
+ if (timeoutHandle.timer !== void 0) {
57658
+ this.releaseWaitClearTimeout(timeoutHandle.timer);
57659
+ }
57660
+ if (outcome === null) {
57661
+ timedOut = true;
57662
+ this.logReleaseNotConfirmed(address, agentId, phase, "close_timeout");
57663
+ return false;
57664
+ }
57665
+ if (outcome.closed) {
57666
+ if (this.pendingReleaseByAddress.get(key) === entry) {
57667
+ this.pendingReleaseByAddress.delete(key);
57668
+ }
57669
+ return true;
57670
+ }
57671
+ if (!outcome.closeFailed) {
57672
+ this.logReleaseNotConfirmed(address, agentId, phase, "close_unavailable");
57673
+ }
57674
+ return false;
57675
+ }
57676
+ // Stops serving `client` to new operations. Every removal is identity
57677
+ // checked, so a late caller can never remove a newer instance (or its replay
57678
+ // gate / recovery / retry state) registered for the same address.
57679
+ unpublishClient(address, client, phase) {
57680
+ const key = address.toLowerCase();
57681
+ let removed = false;
57682
+ for (const [registeredAddress, registered] of this.clients) {
57683
+ if (registered === client && registeredAddress.toLowerCase() === key) {
57684
+ this.clients.delete(registeredAddress);
57685
+ removed = true;
57686
+ }
57687
+ }
57688
+ const gate = this.inboundReplayGates.get(key);
57689
+ if (gate) {
57690
+ const owner = this.inboundReplayGateOwners.get(gate);
57691
+ if (owner === client || owner === void 0 && removed) {
57692
+ this.inboundReplayGates.delete(key);
57693
+ }
57694
+ }
57695
+ this.cancelStreamRecoveryForAddress(address, client);
57696
+ if (removed) {
57697
+ this.replayScanFailuresByAddress.delete(key);
57698
+ this.clearReplayScanRetry(
57699
+ address,
57700
+ phase.startsWith("recycle") ? "client_recycled" : "client_removed"
57701
+ );
57702
+ }
57703
+ if (!this.getClientByAddress(address)) {
57704
+ this.stoppedAddresses.add(key);
57705
+ }
57706
+ }
57707
+ async settlePendingRelease(address) {
57708
+ const entry = this.pendingReleaseByAddress.get(address.toLowerCase());
57709
+ if (!entry) {
57710
+ return true;
57711
+ }
57712
+ if (entry.inFlight) {
57713
+ return false;
57714
+ }
57715
+ const retryPhase = entry.phase.endsWith("/retry") ? entry.phase : `${entry.phase}/retry`;
57716
+ return this.releaseClient(address, entry.client, entry.agentId, retryPhase);
57717
+ }
57657
57718
  async recordInstallationHealth(params) {
57658
57719
  const { address, agent, agentInfo, phase, attempt } = params;
57659
57720
  try {
@@ -57774,8 +57835,6 @@ var XmtpService = class _XmtpService {
57774
57835
  const r = results[i];
57775
57836
  if (r.status === "fulfilled") {
57776
57837
  const { address, agent, agentInfo } = r.value;
57777
- this.stoppedAddresses.delete(address.toLowerCase());
57778
- this.clients.set(address, agent);
57779
57838
  logWithTimestamp(
57780
57839
  `[xmtp-sdk] identity initialized: ${address} (agentId=${agentInfo.agentId})`
57781
57840
  );
@@ -57801,6 +57860,10 @@ var XmtpService = class _XmtpService {
57801
57860
  phase: "init",
57802
57861
  attempt: "1"
57803
57862
  });
57863
+ } else if (r.reason instanceof XmtpClientCreateBlockedError) {
57864
+ logWithTimestamp(
57865
+ `[xmtp-sdk] identity init: create blocked (${r.reason.reason}): ${agents[i].communicationAddress} (agentId=${agents[i].agentId})`
57866
+ );
57804
57867
  } else {
57805
57868
  failedAgents.push(agents[i]);
57806
57869
  if (r.reason instanceof XmtpCreationCooldownSkipError) {
@@ -57837,8 +57900,6 @@ var XmtpService = class _XmtpService {
57837
57900
  const r = retryResults[i];
57838
57901
  if (r.status === "fulfilled") {
57839
57902
  const { address, agent, agentInfo } = r.value;
57840
- this.stoppedAddresses.delete(address.toLowerCase());
57841
- this.clients.set(address, agent);
57842
57903
  logWithTimestamp(
57843
57904
  `[xmtp-sdk] retry succeeded: ${address} (agentId=${agentInfo.agentId})`
57844
57905
  );
@@ -57864,6 +57925,11 @@ var XmtpService = class _XmtpService {
57864
57925
  phase: "init",
57865
57926
  attempt: "2"
57866
57927
  });
57928
+ } else if (r.reason instanceof XmtpClientCreateBlockedError) {
57929
+ const info = failedAgents[i];
57930
+ logWithTimestamp(
57931
+ `[xmtp-sdk] retry create blocked (${r.reason.reason}): ${info.communicationAddress} (agentId=${info.agentId})`
57932
+ );
57867
57933
  } else if (r.reason instanceof XmtpCreationCooldownSkipError) {
57868
57934
  const info = failedAgents[i];
57869
57935
  logWithTimestamp(
@@ -57946,36 +58012,38 @@ var XmtpService = class _XmtpService {
57946
58012
  throw err;
57947
58013
  }
57948
58014
  }
58015
+ for (const pendingKey of [...this.pendingReleaseByAddress.keys()]) {
58016
+ const settled = await this.settlePendingRelease(pendingKey);
58017
+ logWithTimestamp(
58018
+ `[xmtp-sdk] refresh: pending release ${pendingKey} ${settled ? "confirmed" : "still pending"}`
58019
+ );
58020
+ }
57949
58021
  const oldAddresses = new Set(
57950
- this.allAgents.map((a) => a.communicationAddress)
58022
+ this.allAgents.map((a) => a.communicationAddress.toLowerCase())
58023
+ );
58024
+ const newAddresses = new Set(
58025
+ newAgents.map((a) => a.communicationAddress.toLowerCase())
57951
58026
  );
57952
- const newAddresses = new Set(newAgents.map((a) => a.communicationAddress));
57953
58027
  const added = newAgents.filter(
57954
- (a) => !oldAddresses.has(a.communicationAddress) || !this.clients.has(a.communicationAddress)
58028
+ (a) => !oldAddresses.has(a.communicationAddress.toLowerCase()) || !this.getClientByAddress(a.communicationAddress)
57955
58029
  );
57956
58030
  const removed = this.allAgents.filter(
57957
- (a) => !newAddresses.has(a.communicationAddress)
58031
+ (a) => !newAddresses.has(a.communicationAddress.toLowerCase())
57958
58032
  );
57959
58033
  this.allAgents = newAgents;
57960
58034
  for (const agentInfo of removed) {
57961
58035
  const address = agentInfo.communicationAddress;
57962
- const client = this.clients.get(address);
58036
+ const client = this.getClientByAddress(address);
57963
58037
  if (client) {
57964
58038
  try {
57965
- this.cancelStreamRecoveryForAddress(address);
57966
- this.stoppedAddresses.add(address.toLowerCase());
57967
- await stopAndCloseXmtpClient(client, {
58039
+ const released = await this.releaseClient(
57968
58040
  address,
57969
- agentId: agentInfo.agentId,
57970
- phase: "refresh/remove",
57971
- onCloseError: (err) => logger.error(
57972
- LogEvent.XMTP_CLIENT_CLOSE_FAILED,
57973
- err instanceof Error ? err : new Error(String(err)),
57974
- { walletAddress: address, onchainosAgentId: agentInfo.agentId, phase: "refresh/remove" }
57975
- )
57976
- });
58041
+ client,
58042
+ agentInfo.agentId,
58043
+ "refresh/remove"
58044
+ );
57977
58045
  logWithTimestamp(
57978
- `[xmtp-sdk] refresh: stopped client: ${address} (agentId=${agentInfo.agentId})`
58046
+ `[xmtp-sdk] refresh: stopped client: ${address} (agentId=${agentInfo.agentId}) released=${released}`
57979
58047
  );
57980
58048
  } catch (err) {
57981
58049
  logWithTimestamp(`[xmtp-sdk] refresh: failed to stop client: ${address}`, err);
@@ -57985,10 +58053,6 @@ var XmtpService = class _XmtpService {
57985
58053
  phase: "stop-client"
57986
58054
  });
57987
58055
  }
57988
- this.clients.delete(address);
57989
- this.inboundReplayGates.delete(address.toLowerCase());
57990
- this.replayScanFailuresByAddress.delete(address.toLowerCase());
57991
- this.clearReplayScanRetry(address, "client_removed");
57992
58056
  logger.info(LogEvent.AGENT_CLIENT_REMOVED, {
57993
58057
  ...agentExtras({
57994
58058
  walletAddress: address,
@@ -58030,8 +58094,6 @@ var XmtpService = class _XmtpService {
58030
58094
  const r = addResults[i];
58031
58095
  if (r.status === "fulfilled") {
58032
58096
  const { address, agentInfo } = r.value;
58033
- this.stoppedAddresses.delete(address.toLowerCase());
58034
- this.clients.set(address, r.value.agent);
58035
58097
  logWithTimestamp(
58036
58098
  `[xmtp-sdk] refresh: identity initialized: ${address} (agentId=${agentInfo.agentId})`
58037
58099
  );
@@ -58058,6 +58120,10 @@ var XmtpService = class _XmtpService {
58058
58120
  phase: "refresh",
58059
58121
  attempt: "1"
58060
58122
  });
58123
+ } else if (r.reason instanceof XmtpClientCreateBlockedError) {
58124
+ logWithTimestamp(
58125
+ `[xmtp-sdk] refresh: create blocked (${r.reason.reason}): ${added[i].communicationAddress} (agentId=${added[i].agentId})`
58126
+ );
58061
58127
  } else {
58062
58128
  failedAgents.push(added[i]);
58063
58129
  if (r.reason instanceof XmtpCreationCooldownSkipError) {
@@ -58097,8 +58163,6 @@ var XmtpService = class _XmtpService {
58097
58163
  const r = retryResults[i];
58098
58164
  if (r.status === "fulfilled") {
58099
58165
  const { address, agentInfo } = r.value;
58100
- this.stoppedAddresses.delete(address.toLowerCase());
58101
- this.clients.set(address, r.value.agent);
58102
58166
  logWithTimestamp(
58103
58167
  `[xmtp-sdk] refresh: retry succeeded: ${address} (agentId=${agentInfo.agentId})`
58104
58168
  );
@@ -58125,6 +58189,11 @@ var XmtpService = class _XmtpService {
58125
58189
  phase: "refresh",
58126
58190
  attempt: "2"
58127
58191
  });
58192
+ } else if (r.reason instanceof XmtpClientCreateBlockedError) {
58193
+ const info = failedAgents[i];
58194
+ logWithTimestamp(
58195
+ `[xmtp-sdk] refresh: retry create blocked (${r.reason.reason}): ${info.communicationAddress} (agentId=${info.agentId})`
58196
+ );
58128
58197
  } else if (r.reason instanceof XmtpCreationCooldownSkipError) {
58129
58198
  const info = failedAgents[i];
58130
58199
  logWithTimestamp(
@@ -58150,7 +58219,8 @@ var XmtpService = class _XmtpService {
58150
58219
  }
58151
58220
  }
58152
58221
  await this.startListeningForAddresses(
58153
- added.map((a) => a.communicationAddress)
58222
+ added.map((a) => a.communicationAddress),
58223
+ "refresh/listen-failed"
58154
58224
  );
58155
58225
  for (const agentInfo of added) {
58156
58226
  const address = agentInfo.communicationAddress;
@@ -58215,30 +58285,42 @@ var XmtpService = class _XmtpService {
58215
58285
  }
58216
58286
  for (const agentInfo of this.allAgents) {
58217
58287
  const address = agentInfo.communicationAddress;
58218
- const oldClient = this.clients.get(address);
58219
- if (!oldClient) {
58288
+ const addressKey = address.toLowerCase();
58289
+ const oldClient = this.getClientByAddress(address);
58290
+ const hasPendingRelease = this.pendingReleaseByAddress.has(addressKey) || this.releaseConfirmedNeedsCreate.has(addressKey);
58291
+ if (!oldClient && !hasPendingRelease) {
58220
58292
  continue;
58221
58293
  }
58222
- const addressKey = address.toLowerCase();
58223
- try {
58224
- this.cancelStreamRecoveryForAddress(address);
58225
- this.stoppedAddresses.add(addressKey);
58226
- await stopAndCloseXmtpClient(oldClient, {
58227
- address,
58228
- agentId: agentInfo.agentId,
58229
- phase: "recycle",
58230
- onCloseError: (err) => logger.error(
58231
- LogEvent.XMTP_CLIENT_CLOSE_FAILED,
58232
- err instanceof Error ? err : new Error(String(err)),
58233
- { walletAddress: address, onchainosAgentId: agentInfo.agentId, phase: "recycle" }
58234
- )
58235
- });
58236
- this.clients.delete(address);
58237
- this.inboundReplayGates.delete(addressKey);
58238
- this.replayScanFailuresByAddress.delete(addressKey);
58239
- this.clearReplayScanRetry(address, "client_recycled");
58294
+ if (!oldClient) {
58295
+ let settled = false;
58296
+ try {
58297
+ settled = await this.settlePendingRelease(address);
58298
+ } catch (err) {
58299
+ logWithTimestamp(`[xmtp-sdk] recycle: pending release retry failed: ${address}`, err);
58300
+ }
58301
+ if (!settled) {
58302
+ failed++;
58303
+ continue;
58304
+ }
58305
+ } else {
58306
+ let released = false;
58307
+ try {
58308
+ released = await this.releaseClient(
58309
+ address,
58310
+ oldClient,
58311
+ agentInfo.agentId,
58312
+ "recycle"
58313
+ );
58314
+ } catch (err) {
58315
+ logWithTimestamp(`[xmtp-sdk] recycle: failed to stop client: ${address}`, err);
58316
+ logger.error(LogEvent.AGENT_REFRESH_FAILED, err instanceof Error ? err : new Error(String(err)), {
58317
+ walletAddress: address,
58318
+ onchainosAgentId: agentInfo.agentId,
58319
+ phase: "recycle/stop-client"
58320
+ });
58321
+ }
58240
58322
  logWithTimestamp(
58241
- `[xmtp-sdk] recycle: stopped client: ${address} (agentId=${agentInfo.agentId})`
58323
+ `[xmtp-sdk] recycle: stopped client: ${address} (agentId=${agentInfo.agentId}) released=${released}`
58242
58324
  );
58243
58325
  logger.info(LogEvent.AGENT_CLIENT_REMOVED, {
58244
58326
  ...agentExtras({
@@ -58248,23 +58330,18 @@ var XmtpService = class _XmtpService {
58248
58330
  }),
58249
58331
  phase: "recycle"
58250
58332
  });
58251
- } catch (err) {
58252
- failed++;
58253
- this.stoppedAddresses.delete(addressKey);
58254
- logWithTimestamp(`[xmtp-sdk] recycle: failed to stop client: ${address}`, err);
58255
- logger.error(LogEvent.AGENT_REFRESH_FAILED, err instanceof Error ? err : new Error(String(err)), {
58256
- walletAddress: address,
58257
- onchainosAgentId: agentInfo.agentId,
58258
- phase: "recycle/stop-client"
58259
- });
58260
- continue;
58333
+ if (!released) {
58334
+ failed++;
58335
+ continue;
58336
+ }
58261
58337
  }
58338
+ let newAgent;
58339
+ let newAgentReleased = false;
58262
58340
  try {
58263
58341
  const { agent } = await this.createClientForAgent(agentInfo, {
58264
58342
  logPrefix: "[xmtp-sdk:recycle]"
58265
58343
  });
58266
- this.stoppedAddresses.delete(addressKey);
58267
- this.clients.set(address, agent);
58344
+ newAgent = agent;
58268
58345
  logWithTimestamp(
58269
58346
  `[xmtp-sdk] recycle: identity initialized: ${address} (agentId=${agentInfo.agentId})`
58270
58347
  );
@@ -58288,7 +58365,13 @@ var XmtpService = class _XmtpService {
58288
58365
  agentInfo,
58289
58366
  phase: "recycle"
58290
58367
  });
58291
- await this.startListeningForAddresses([address]);
58368
+ const listen = (await this.startListeningForAddresses([address], "recycle/listen-failed")).get(address);
58369
+ if (listen?.client !== agent || !isListenHealthy(listen.outcome)) {
58370
+ newAgentReleased = listen?.client === agent && listen.outcome === "failed";
58371
+ throw new Error(
58372
+ `xmtp listener not started (${listen?.client === agent ? listen.outcome : "client_replaced"})`
58373
+ );
58374
+ }
58292
58375
  const replayGate = this.inboundReplayGates.get(addressKey);
58293
58376
  let replaySummary;
58294
58377
  try {
@@ -58307,8 +58390,21 @@ var XmtpService = class _XmtpService {
58307
58390
  recycled++;
58308
58391
  } catch (err) {
58309
58392
  failed++;
58310
- this.cancelStreamRecoveryForAddress(address);
58311
- this.clients.delete(address);
58393
+ if (newAgent && !newAgentReleased) {
58394
+ try {
58395
+ await this.releaseClient(
58396
+ address,
58397
+ newAgent,
58398
+ agentInfo.agentId,
58399
+ "recycle/create-failed"
58400
+ );
58401
+ } catch (releaseErr) {
58402
+ logWithTimestamp(
58403
+ `[xmtp-sdk] recycle: failed to release new client: ${address}`,
58404
+ releaseErr
58405
+ );
58406
+ }
58407
+ }
58312
58408
  logWithTimestamp(`[xmtp-sdk] recycle: failed to recreate client: ${address}`, err);
58313
58409
  logger.error(
58314
58410
  LogEvent.XMTP_CONNECTION_FAILED,
@@ -58712,7 +58808,7 @@ var XmtpService = class _XmtpService {
58712
58808
  }
58713
58809
  }
58714
58810
  async startListening() {
58715
- await this.startListeningForAddresses([...this.clients.keys()]);
58811
+ await this.startListeningForAddresses([...this.clients.keys()], "listen-failed");
58716
58812
  }
58717
58813
  async drainInboundReplayGate(address, expectedGate) {
58718
58814
  if (!expectedGate) {
@@ -58777,11 +58873,22 @@ var XmtpService = class _XmtpService {
58777
58873
  );
58778
58874
  return gate;
58779
58875
  }
58780
- cancelStreamRecoveryForAddress(address) {
58876
+ // With `client`, only that client's recovery is cancelled, so a late caller
58877
+ // cannot cancel the recovery of a newer instance on the same address.
58878
+ cancelStreamRecoveryForAddress(address, client) {
58781
58879
  const addressKey = address.toLowerCase();
58782
- const cleanup = this.streamRecoveryCleanupByAddress.get(addressKey);
58880
+ const entry = this.streamRecoveryCleanupByAddress.get(addressKey);
58881
+ if (!entry || client && entry.client !== client) {
58882
+ return;
58883
+ }
58783
58884
  this.streamRecoveryCleanupByAddress.delete(addressKey);
58784
- cleanup?.();
58885
+ entry.cleanup();
58886
+ }
58887
+ // True while `client` is the registered client of `address` (case-insensitive)
58888
+ // and the address is neither stopped nor being released.
58889
+ isCurrentListenOwner(address, client) {
58890
+ const key = address.toLowerCase();
58891
+ return this.getClientByAddress(address) === client && !this.stoppedAddresses.has(key) && !this.pendingReleaseByAddress.has(key);
58785
58892
  }
58786
58893
  getClientGeneration(client) {
58787
58894
  const existing = this.clientGenerationByClient.get(client);
@@ -58933,10 +59040,17 @@ var XmtpService = class _XmtpService {
58933
59040
  this.notifyAgentsWakeupAfterReplay();
58934
59041
  return summary;
58935
59042
  }
58936
- async startListeningForAddresses(addresses) {
59043
+ // Starts (at most once per client) the listener of every registered address
59044
+ // and reports each outcome. A "failed" client, i.e. one with neither a live
59045
+ // listener nor an owned retry task, is released with `releasePhase` before
59046
+ // this returns, so it is never served as a healthy instance.
59047
+ async startListeningForAddresses(addresses, releasePhase = "listen-failed") {
58937
59048
  const valid = addresses.filter((addr) => this.clients.has(addr));
58938
- await parallelMap(valid, async (address) => {
58939
- const agent = this.clients.get(address);
59049
+ const targets = valid.map((address) => ({
59050
+ address,
59051
+ client: this.clients.get(address)
59052
+ }));
59053
+ const listenForClient = async (address, agent) => {
58940
59054
  const clientGeneration = this.getClientGeneration(agent);
58941
59055
  const addressKey = address.toLowerCase();
58942
59056
  const tag = `[xmtp-sdk:${address}]`;
@@ -58947,6 +59061,11 @@ var XmtpService = class _XmtpService {
58947
59061
  onchainosAgentId: onchainosAgent?.agentId,
58948
59062
  role: onchainosAgent?.role
58949
59063
  };
59064
+ const ownsAddress = () => this.isCurrentListenOwner(address, agent);
59065
+ if (!ownsAddress()) {
59066
+ logWithTimestamp(`${tag} listener setup skipped: client no longer current`);
59067
+ return "skipped";
59068
+ }
58950
59069
  try {
58951
59070
  await agent.client.conversations.syncAll([
58952
59071
  import_node_bindings2.ConsentState.Allowed,
@@ -58954,13 +59073,21 @@ var XmtpService = class _XmtpService {
58954
59073
  ]);
58955
59074
  logWithTimestamp(`${tag} conversations synced (non-Denied)`);
58956
59075
  } catch (err) {
58957
- logWithTimestamp(`${tag} conversation sync failed, skipping this client:`, err);
59076
+ if (!ownsAddress()) {
59077
+ logWithTimestamp(`${tag} stale conversation sync failed after replacement, ignored:`, err);
59078
+ return "skipped";
59079
+ }
59080
+ logWithTimestamp(`${tag} conversation sync failed, listener not started:`, err);
58958
59081
  logger.error(
58959
59082
  LogEvent.CONVERSATIONS_STREAM_FAILED,
58960
59083
  err instanceof Error ? err : void 0,
58961
59084
  agentExtras(identity)
58962
59085
  );
58963
- return;
59086
+ return "failed";
59087
+ }
59088
+ if (!ownsAddress()) {
59089
+ logWithTimestamp(`${tag} listener setup skipped after sync: client no longer current`);
59090
+ return "skipped";
58964
59091
  }
58965
59092
  agent.use(loggingMiddleware(identity));
58966
59093
  agent.use(selfFilterMiddleware());
@@ -58989,6 +59116,7 @@ var XmtpService = class _XmtpService {
58989
59116
  });
58990
59117
  const gate = new InboundReplayGate(inbound);
58991
59118
  this.inboundReplayGates.set(address.toLowerCase(), gate);
59119
+ this.inboundReplayGateOwners.set(gate, agent);
58992
59120
  agent.use(gate.middleware);
58993
59121
  } else {
58994
59122
  logWithTimestamp(
@@ -59006,16 +59134,25 @@ var XmtpService = class _XmtpService {
59006
59134
  const MAX_RETRIES = 5;
59007
59135
  const BASE_DELAY_MS = 1e3;
59008
59136
  const startWithRetry = async (attempt = 0) => {
59009
- if (this.stoppedAddresses.has(address.toLowerCase()) || !this.clients.has(address)) {
59137
+ if (!ownsAddress()) {
59010
59138
  logWithTimestamp(`${tag} start skipped: client stopped or removed`);
59011
- return;
59139
+ return "skipped";
59012
59140
  }
59013
59141
  try {
59014
59142
  const liveStreamOptions = {
59015
59143
  consentStates: [import_node_bindings2.ConsentState.Allowed, import_node_bindings2.ConsentState.Unknown]
59016
59144
  };
59017
59145
  await agent.start(liveStreamOptions);
59146
+ if (!ownsAddress()) {
59147
+ logWithTimestamp(`${tag} stale agent.start resolved after replacement, ignored`);
59148
+ return "skipped";
59149
+ }
59150
+ return "started";
59018
59151
  } catch (err) {
59152
+ if (!ownsAddress()) {
59153
+ logWithTimestamp(`${tag} stale agent.start failed after replacement, ignored:`, err);
59154
+ return "skipped";
59155
+ }
59019
59156
  logWithTimestamp(`${tag} agent.start error (attempt=${attempt}):`, err);
59020
59157
  logger.error(
59021
59158
  LogEvent.AGENT_START_FAILED,
@@ -59025,17 +59162,27 @@ var XmtpService = class _XmtpService {
59025
59162
  attempt: String(attempt)
59026
59163
  }
59027
59164
  );
59028
- scheduleRetry(attempt);
59165
+ return scheduleRetry(attempt);
59029
59166
  }
59030
59167
  };
59031
59168
  const scheduleRetry = (attempt) => {
59032
- if (this.stoppedAddresses.has(address.toLowerCase()) || !this.clients.has(address)) {
59169
+ if (!ownsAddress()) {
59033
59170
  logWithTimestamp(`${tag} reconnect skipped: client stopped or removed`);
59034
- return;
59171
+ return "skipped";
59035
59172
  }
59036
59173
  if (attempt >= MAX_RETRIES) {
59037
- logWithTimestamp(`${tag} reached max retries (${MAX_RETRIES}), giving up reconnect`);
59038
- return;
59174
+ logWithTimestamp(
59175
+ `${tag} reached max retries (${MAX_RETRIES}), giving up reconnect; releasing client`
59176
+ );
59177
+ void this.releaseClient(
59178
+ address,
59179
+ agent,
59180
+ identity.onchainosAgentId ?? "",
59181
+ "listen/retry-exhausted"
59182
+ ).catch((err) => {
59183
+ logWithTimestamp(`${tag} release after retry exhaustion failed:`, err);
59184
+ });
59185
+ return "failed";
59039
59186
  }
59040
59187
  const delay = BASE_DELAY_MS * 2 ** attempt;
59041
59188
  logWithTimestamp(`${tag} reconnecting in ${delay}ms (attempt=${attempt + 1})`);
@@ -59043,6 +59190,7 @@ var XmtpService = class _XmtpService {
59043
59190
  () => void startWithRetry(attempt + 1),
59044
59191
  delay
59045
59192
  );
59193
+ return "retrying";
59046
59194
  };
59047
59195
  const streamRecovery = new StreamRecoveryTelemetry();
59048
59196
  let recoveryTimeout;
@@ -59062,10 +59210,10 @@ var XmtpService = class _XmtpService {
59062
59210
  recoveryStabilityTimeout = void 0;
59063
59211
  }
59064
59212
  };
59065
- this.streamRecoveryCleanupByAddress.set(
59066
- addressKey,
59067
- cleanupStreamRecovery
59068
- );
59213
+ this.streamRecoveryCleanupByAddress.set(addressKey, {
59214
+ client: agent,
59215
+ cleanup: cleanupStreamRecovery
59216
+ });
59069
59217
  agent.on("unhandledError", (err) => {
59070
59218
  if (recoveryDisposed || this.clients.get(address) !== agent || this.stoppedAddresses.has(addressKey)) {
59071
59219
  return;
@@ -59227,9 +59375,54 @@ var XmtpService = class _XmtpService {
59227
59375
  `${tag} agent message event msg=${msg?.id ?? "(unknown)"} kind=${msg?.kind ?? "(unknown)"} conv=${conversation?.id ?? msg?.conversationId ?? "(unknown)"} sender=${msg?.senderInboxId ?? "(unknown)"} isText=${typeof ctx.isText === "function" ? String(ctx.isText()) : "unknown"} preview="${previewDebugContent(msg?.content)}"`
59228
59376
  );
59229
59377
  });
59230
- await startWithRetry();
59231
- logWithTimestamp(`${tag} message listener started`);
59378
+ const outcome = await startWithRetry();
59379
+ logWithTimestamp(`${tag} message listener ${outcome}`);
59380
+ return outcome;
59381
+ };
59382
+ const settled = await parallelMap(targets, async ({ address, client }) => {
59383
+ let task = this.listenTaskByClient.get(client);
59384
+ if (!task) {
59385
+ task = listenForClient(address, client);
59386
+ this.listenTaskByClient.set(client, task);
59387
+ }
59388
+ let outcome;
59389
+ try {
59390
+ outcome = await task;
59391
+ } catch (err) {
59392
+ logWithTimestamp(`[xmtp-sdk:${address}] listener setup failed:`, err);
59393
+ logger.error(
59394
+ LogEvent.AGENT_START_FAILED,
59395
+ err instanceof Error ? err : new Error(String(err)),
59396
+ {
59397
+ ...agentExtras({
59398
+ walletAddress: address,
59399
+ inboxId: client.client?.inboxId,
59400
+ onchainosAgentId: this.getAgentByAddress(address)?.agentId
59401
+ }),
59402
+ phase: "listener-setup"
59403
+ }
59404
+ );
59405
+ outcome = "failed";
59406
+ }
59407
+ if (outcome === "failed") {
59408
+ await this.releaseClient(
59409
+ address,
59410
+ client,
59411
+ this.getAgentByAddress(address)?.agentId ?? "",
59412
+ releasePhase
59413
+ );
59414
+ }
59415
+ return outcome;
59416
+ });
59417
+ const results = /* @__PURE__ */ new Map();
59418
+ targets.forEach(({ address, client }, i) => {
59419
+ const r = settled[i];
59420
+ results.set(address, {
59421
+ client,
59422
+ outcome: r.status === "fulfilled" ? r.value : "failed"
59423
+ });
59232
59424
  });
59425
+ return results;
59233
59426
  }
59234
59427
  async replayOfflineMessagesForAddress(address, expectedClient, trigger = "periodic_repair", recoveryIdentity) {
59235
59428
  const addressReplayStartedAt = Date.now();
@@ -59705,7 +59898,7 @@ function buildSendEnvelope(params) {
59705
59898
  init_log();
59706
59899
  init_sentry_logger();
59707
59900
  init_log_fields();
59708
- var import_node_crypto12 = require("node:crypto");
59901
+ var import_node_crypto11 = require("node:crypto");
59709
59902
 
59710
59903
  // ../core/src/a2a/concurrency.ts
59711
59904
  async function withSharedPromise(registry, key, fn) {
@@ -61107,17 +61300,17 @@ init_ai_provider();
61107
61300
 
61108
61301
  // src/agent-message-notice.ts
61109
61302
  init_log();
61110
- var import_node_crypto11 = require("node:crypto");
61303
+ var import_node_crypto10 = require("node:crypto");
61111
61304
  init_session_store();
61112
61305
  init_ai_provider();
61113
61306
 
61114
61307
  // src/outbound-behavior.ts
61115
61308
  init_log();
61116
- var import_node_crypto10 = require("node:crypto");
61309
+ var import_node_crypto9 = require("node:crypto");
61117
61310
 
61118
61311
  // src/openclaw-gateway.ts
61119
61312
  init_log();
61120
- var import_node_crypto9 = require("node:crypto");
61313
+ var import_node_crypto8 = require("node:crypto");
61121
61314
 
61122
61315
  // ../core/src/openclaw-gateway-config.ts
61123
61316
  var import_node_fs17 = require("node:fs");
@@ -61610,7 +61803,7 @@ async function callDeleteSessions(params) {
61610
61803
  return await callOpenClawGateway({ method: "okx-a2a.delete_sessions", params });
61611
61804
  }
61612
61805
  async function callSessionsSend(params) {
61613
- const idempotencyKey = params.idempotencyKey ?? (0, import_node_crypto9.randomUUID)();
61806
+ const idempotencyKey = params.idempotencyKey ?? (0, import_node_crypto8.randomUUID)();
61614
61807
  const sendParams = { key: params.key, message: params.message, idempotencyKey };
61615
61808
  try {
61616
61809
  return await callOpenClawGateway({ method: "sessions.send", params: sendParams });
@@ -61726,7 +61919,7 @@ async function sleep3(ms) {
61726
61919
  var MinimalGatewayClient = class {
61727
61920
  config;
61728
61921
  protocolVersion;
61729
- instanceId = (0, import_node_crypto9.randomUUID)();
61922
+ instanceId = (0, import_node_crypto8.randomUUID)();
61730
61923
  pending = /* @__PURE__ */ new Map();
61731
61924
  ws = null;
61732
61925
  ready = false;
@@ -61814,7 +62007,7 @@ var MinimalGatewayClient = class {
61814
62007
  }));
61815
62008
  }
61816
62009
  const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
61817
- const id = `okx-a2a-${++this.requestSeq}-${(0, import_node_crypto9.randomUUID)()}`;
62010
+ const id = `okx-a2a-${++this.requestSeq}-${(0, import_node_crypto8.randomUUID)()}`;
61818
62011
  const frame = { type: "req", id, method, params };
61819
62012
  return new Promise((resolve11, reject) => {
61820
62013
  const timer = setTimeout(() => {
@@ -61940,7 +62133,7 @@ function buildConnectParams(config, instanceId, protocolVersion) {
61940
62133
  client: {
61941
62134
  id: "gateway-client",
61942
62135
  displayName: "okx-a2a-node",
61943
- version: "0.2.18-beta-4dd056b897-261015113839",
62136
+ version: "0.2.18",
61944
62137
  platform: "node",
61945
62138
  mode: "backend",
61946
62139
  instanceId
@@ -61951,7 +62144,7 @@ function buildConnectParams(config, instanceId, protocolVersion) {
61951
62144
  commands: [],
61952
62145
  permissions: {},
61953
62146
  locale: Intl.DateTimeFormat().resolvedOptions().locale || "en-US",
61954
- userAgent: `okx-a2a-node/${"0.2.18-beta-4dd056b897-261015113839"}`,
62147
+ userAgent: `okx-a2a-node/${"0.2.18"}`,
61955
62148
  auth: {
61956
62149
  ...config.token ? { token: config.token } : {},
61957
62150
  ...config.password ? { password: config.password } : {}
@@ -62557,7 +62750,7 @@ function resolveSessionGateFallbackMs(env = process.env) {
62557
62750
  return DEFAULT_SESSION_GATE_FALLBACK_MS;
62558
62751
  }
62559
62752
  function resolveUserDeliveryId(input) {
62560
- return input.idempotencyKey?.trim() || (0, import_node_crypto10.randomUUID)();
62753
+ return input.idempotencyKey?.trim() || (0, import_node_crypto9.randomUUID)();
62561
62754
  }
62562
62755
  var GATEWAY_RPC_TRANSPORT = "gateway_rpc";
62563
62756
  var USER_CHANNEL_TRANSPORT = "user_channel";
@@ -63471,7 +63664,7 @@ function buildSystemMessageIdempotencyKey(input) {
63471
63664
  return `system-message:${identity}`;
63472
63665
  }
63473
63666
  function stableHash2(value) {
63474
- return (0, import_node_crypto11.createHash)("sha256").update(value).digest("hex").slice(0, 24);
63667
+ return (0, import_node_crypto10.createHash)("sha256").update(value).digest("hex").slice(0, 24);
63475
63668
  }
63476
63669
 
63477
63670
  // src/xmtp-send.ts
@@ -63940,7 +64133,7 @@ async function handleSqliteGroupSendCommand(params) {
63940
64133
  role: senderAgent?.role,
63941
64134
  sendDurationMs: Date.now() - sendStartMs
63942
64135
  });
63943
- const messageId = `outbound-${(0, import_node_crypto12.randomUUID)()}`;
64136
+ const messageId = `outbound-${(0, import_node_crypto11.randomUUID)()}`;
63944
64137
  await notifyAgentMessageToUserAttention({
63945
64138
  direction: "outbound" /* OUTBOUND */,
63946
64139
  sender: {
@@ -64061,7 +64254,7 @@ async function handleGroupSendCommand(params) {
64061
64254
  sendDurationMs: Date.now() - sendStartMs
64062
64255
  });
64063
64256
  const now = Date.now();
64064
- const messageId = `outbound-${(0, import_node_crypto12.randomUUID)()}`;
64257
+ const messageId = `outbound-${(0, import_node_crypto11.randomUUID)()}`;
64065
64258
  const stored = {
64066
64259
  id: messageId,
64067
64260
  direction: "outbound",
@@ -64280,7 +64473,7 @@ async function handleXmtpSendCommand(params) {
64280
64473
  sendDurationMs: Date.now() - sendStartMs
64281
64474
  });
64282
64475
  const now = Date.now();
64283
- const messageId = `outbound-${(0, import_node_crypto12.randomUUID)()}`;
64476
+ const messageId = `outbound-${(0, import_node_crypto11.randomUUID)()}`;
64284
64477
  const stored = {
64285
64478
  id: messageId,
64286
64479
  direction: "outbound",
@@ -64327,357 +64520,6 @@ async function handleXmtpSendCommand(params) {
64327
64520
  }
64328
64521
  }
64329
64522
 
64330
- // src/subscription-push.ts
64331
- init_log();
64332
- init_sentry_logger();
64333
-
64334
- // ../core/src/a2a/subscription-types.ts
64335
- var SUBSCRIPTION_MESSAGE_TYPE = "a2a-subscription-push";
64336
-
64337
- // ../core/src/a2a/subscription-envelope.ts
64338
- function isPlainObject2(value) {
64339
- return !!value && typeof value === "object" && !Array.isArray(value);
64340
- }
64341
- function buildSubscriptionEnvelope(params) {
64342
- const envelope = {
64343
- msgType: SUBSCRIPTION_MESSAGE_TYPE,
64344
- content: params.content,
64345
- senderAgentId: params.senderAgentId
64346
- };
64347
- if (params.deliveryId) {
64348
- envelope.deliveryId = params.deliveryId;
64349
- }
64350
- return JSON.stringify(envelope);
64351
- }
64352
- function isSubscriptionEnvelope(payload) {
64353
- return isPlainObject2(payload) && payload.msgType === SUBSCRIPTION_MESSAGE_TYPE;
64354
- }
64355
- function isNonEmptyString(value) {
64356
- return typeof value === "string" && value.length > 0;
64357
- }
64358
- function readSubscriptionEnvelope(payload) {
64359
- if (!isSubscriptionEnvelope(payload)) {
64360
- return { ok: false, reason: "not_subscription" };
64361
- }
64362
- const record = payload;
64363
- if (!isNonEmptyString(record.content)) {
64364
- return { ok: false, reason: "missing_content" };
64365
- }
64366
- const envelope = {
64367
- msgType: SUBSCRIPTION_MESSAGE_TYPE,
64368
- content: record.content,
64369
- senderAgentId: isNonEmptyString(record.senderAgentId) ? record.senderAgentId : ""
64370
- };
64371
- if (isNonEmptyString(record.deliveryId)) {
64372
- envelope.deliveryId = record.deliveryId;
64373
- }
64374
- return { ok: true, envelope };
64375
- }
64376
-
64377
- // src/subscription-telemetry.ts
64378
- init_log_fields();
64379
- var SUBSCRIPTION_TRANSPORT = "xmtp";
64380
- function definedExtras(input) {
64381
- return Object.entries(input).reduce((out, [key, value]) => {
64382
- if (typeof value === "string" && value.trim().length > 0) {
64383
- out[key] = value.trim();
64384
- }
64385
- return out;
64386
- }, {});
64387
- }
64388
- function countExtras(input) {
64389
- return Object.entries(input).reduce((out, [key, value]) => {
64390
- if (typeof value === "number" && Number.isFinite(value)) {
64391
- out[key] = String(value);
64392
- }
64393
- return out;
64394
- }, {});
64395
- }
64396
- function buildSubscriptionSendExtras(input) {
64397
- return {
64398
- stage: input.checkpoint,
64399
- ...logFieldExtras({
64400
- checkpoint: input.checkpoint,
64401
- outcome: input.outcome ?? null,
64402
- transport: SUBSCRIPTION_TRANSPORT,
64403
- eventFamily: "outbound",
64404
- deliveryId: input.deliveryId ?? null
64405
- }),
64406
- ...definedExtras({
64407
- aspAgentId: input.aspAgentId,
64408
- conversationId: input.conversationId,
64409
- reason: input.reason
64410
- }),
64411
- ...countExtras({
64412
- targetCount: input.targetCount,
64413
- sentCount: input.sentCount,
64414
- failedCount: input.failedCount,
64415
- notGroupCount: input.notGroupCount
64416
- })
64417
- };
64418
- }
64419
- function buildSubscriptionInboundExtras(input) {
64420
- return {
64421
- stage: input.checkpoint,
64422
- ...logFieldExtras({
64423
- checkpoint: input.checkpoint,
64424
- outcome: input.outcome ?? null,
64425
- transport: SUBSCRIPTION_TRANSPORT,
64426
- eventFamily: "inbound",
64427
- deliveryId: input.deliveryId ?? null
64428
- }),
64429
- ...definedExtras({
64430
- userAgentId: input.userAgentId,
64431
- conversationId: input.conversationId,
64432
- messageId: input.messageId,
64433
- senderInboxId: input.senderInboxId,
64434
- reason: input.reason,
64435
- errorCode: input.errorCode
64436
- }),
64437
- ...countExtras({
64438
- returnedCount: input.returnedCount,
64439
- invalidCount: input.invalidCount,
64440
- ownedCount: input.ownedCount,
64441
- ignoredCount: input.ignoredCount
64442
- })
64443
- };
64444
- }
64445
- function buildSubscriptionJobExtras(input) {
64446
- return {
64447
- stage: input.checkpoint,
64448
- ...logFieldExtras({
64449
- checkpoint: input.checkpoint,
64450
- outcome: input.outcome,
64451
- transport: SUBSCRIPTION_TRANSPORT,
64452
- eventFamily: "dispatch",
64453
- deliveryId: input.deliveryId ?? null
64454
- }),
64455
- ...definedExtras({
64456
- jobId: input.jobId,
64457
- userAgentId: input.userAgentId,
64458
- aspAgentId: input.aspAgentId,
64459
- conversationId: input.conversationId,
64460
- reason: input.reason
64461
- }),
64462
- ...countExtras({
64463
- total: input.total,
64464
- started: input.started,
64465
- failed: input.failed,
64466
- skippedDuplicate: input.skippedDuplicate
64467
- })
64468
- };
64469
- }
64470
-
64471
- // src/subscription-push.ts
64472
- var DEFAULT_CONCURRENCY = 20;
64473
- var conversationSyncPromises2 = /* @__PURE__ */ new WeakMap();
64474
- function describeError(err) {
64475
- if (err instanceof Error) {
64476
- return err.message;
64477
- }
64478
- if (typeof err === "string" && err.length > 0) {
64479
- return err;
64480
- }
64481
- return "unknown error";
64482
- }
64483
- async function requireXmtpClient2(service, address) {
64484
- const existing = service.getClientByAddress(address);
64485
- if (existing) {
64486
- return existing;
64487
- }
64488
- await service.refreshAgents();
64489
- const refreshed = service.getClientByAddress(address);
64490
- if (!refreshed) {
64491
- throw new Error(`no XMTP client found for ${address}`);
64492
- }
64493
- return refreshed;
64494
- }
64495
- function resolveLocalAddress(service, myAgentId) {
64496
- const address = service.getAddressByAgentId(myAgentId);
64497
- if (!address) {
64498
- throw new Error(`No local communication address found for myAgentId=${myAgentId}`);
64499
- }
64500
- return address;
64501
- }
64502
- async function syncConversationsOnLocalMiss2(agent) {
64503
- const conversations = agent.client.conversations;
64504
- const existing = conversationSyncPromises2.get(conversations);
64505
- if (existing) {
64506
- return existing;
64507
- }
64508
- const pending = conversations.sync();
64509
- conversationSyncPromises2.set(conversations, pending);
64510
- try {
64511
- await pending;
64512
- } finally {
64513
- if (conversationSyncPromises2.get(conversations) === pending) {
64514
- conversationSyncPromises2.delete(conversations);
64515
- }
64516
- }
64517
- }
64518
- async function findGroupConversation2(agent, conversationId) {
64519
- let conversation = await agent.client.conversations.getConversationById(conversationId);
64520
- if (!(conversation instanceof Group)) {
64521
- await syncConversationsOnLocalMiss2(agent);
64522
- conversation = await agent.client.conversations.getConversationById(conversationId);
64523
- }
64524
- return conversation instanceof Group ? conversation : null;
64525
- }
64526
- async function sendSubscriptionToGroup(params) {
64527
- const { agent, conversationId, command, myXmtpAddress, senderRole } = params;
64528
- let conversation;
64529
- try {
64530
- conversation = await findGroupConversation2(agent, conversationId);
64531
- } catch (err) {
64532
- return { conversationId, status: "not_group", error: describeError(err) };
64533
- }
64534
- if (!conversation) {
64535
- return {
64536
- conversationId,
64537
- status: "not_group",
64538
- error: `conversationId=${conversationId} is not a Group (DM or unknown conversation)`
64539
- };
64540
- }
64541
- const envelope = buildSubscriptionEnvelope({
64542
- content: command.content,
64543
- senderAgentId: command.myAgentId,
64544
- deliveryId: command.deliveryId
64545
- });
64546
- const sendStartMs = Date.now();
64547
- try {
64548
- const xmtpMessageId = await conversation.sendText(envelope);
64549
- logXmtpMessageSent({
64550
- xmtpMessageId,
64551
- conversationId,
64552
- // V2 has no job dimension (FR-1) — deliveryId (or a fixed marker)
64553
- // stands in for the telemetry taxonomy's jobId slot.
64554
- jobId: command.deliveryId ?? "subscription-push",
64555
- chatType: "group",
64556
- component: "node_xmtp_subscription_push",
64557
- myXmtpAddress,
64558
- senderAgentId: command.myAgentId,
64559
- role: senderRole,
64560
- sendDurationMs: Date.now() - sendStartMs
64561
- });
64562
- const messageId = typeof xmtpMessageId === "string" && xmtpMessageId.length > 0 ? xmtpMessageId : String(xmtpMessageId);
64563
- logWithTimestamp(
64564
- `[okx-agent-task] subscription-push sent conversationId=${conversationId} deliveryId=${command.deliveryId ?? "(none)"}`
64565
- );
64566
- return { conversationId, status: "sent", messageId };
64567
- } catch (err) {
64568
- logWithTimestamp(
64569
- `[okx-agent-task] subscription-push failed conversationId=${conversationId} deliveryId=${command.deliveryId ?? "(none)"}`
64570
- );
64571
- return { conversationId, status: "failed", error: describeError(err) };
64572
- }
64573
- }
64574
- function summarizeSubscriptionPush(results) {
64575
- let sentCount = 0;
64576
- let failedCount = 0;
64577
- for (const result of results) {
64578
- if (result.status === "sent") {
64579
- sentCount++;
64580
- } else {
64581
- failedCount++;
64582
- }
64583
- }
64584
- return { conversationCount: results.length, sentCount, failedCount };
64585
- }
64586
- async function handleSubscriptionPushCommand(params) {
64587
- const { command, service } = params;
64588
- const aspAgentId = command.myAgentId;
64589
- const deliveryId = command.deliveryId;
64590
- const conversationIds = command.conversationIds ?? [];
64591
- logger.info(
64592
- LogEvent.SUBSCRIPTION_PUSH_STARTED,
64593
- buildSubscriptionSendExtras({
64594
- checkpoint: "outbound/subscription_push_started",
64595
- aspAgentId,
64596
- deliveryId,
64597
- targetCount: conversationIds.length
64598
- })
64599
- );
64600
- if (conversationIds.length === 0) {
64601
- logger.info(
64602
- LogEvent.SUBSCRIPTION_PUSH_EMPTY_TARGETS,
64603
- buildSubscriptionSendExtras({
64604
- checkpoint: "outbound/subscription_push_empty_targets",
64605
- outcome: "ignored",
64606
- aspAgentId,
64607
- deliveryId,
64608
- targetCount: 0,
64609
- reason: "empty_targets"
64610
- })
64611
- );
64612
- return { conversationCount: 0, sentCount: 0, failedCount: 0, results: [] };
64613
- }
64614
- const myXmtpAddress = resolveLocalAddress(service, command.myAgentId);
64615
- const agent = await requireXmtpClient2(service, myXmtpAddress);
64616
- const senderRole = service.getAgentByAddress?.(myXmtpAddress)?.role;
64617
- logger.info(
64618
- LogEvent.SUBSCRIPTION_PUSH_TARGETS_RESOLVED,
64619
- buildSubscriptionSendExtras({
64620
- checkpoint: "outbound/subscription_push_targets_resolved",
64621
- aspAgentId,
64622
- deliveryId,
64623
- targetCount: conversationIds.length
64624
- })
64625
- );
64626
- const settled = await parallelMap(
64627
- conversationIds,
64628
- (conversationId) => sendSubscriptionToGroup({
64629
- agent,
64630
- conversationId,
64631
- command,
64632
- myXmtpAddress,
64633
- senderRole
64634
- }),
64635
- DEFAULT_CONCURRENCY
64636
- );
64637
- const results = settled.map((outcome, index2) => {
64638
- if (outcome.status === "fulfilled") {
64639
- return outcome.value;
64640
- }
64641
- return {
64642
- conversationId: conversationIds[index2],
64643
- status: "failed",
64644
- error: describeError(outcome.reason)
64645
- };
64646
- });
64647
- for (const result of results) {
64648
- if (result.status === "sent") {
64649
- continue;
64650
- }
64651
- logger.error(
64652
- LogEvent.SUBSCRIPTION_PUSH_TARGET_FAILED,
64653
- void 0,
64654
- buildSubscriptionSendExtras({
64655
- checkpoint: "outbound/subscription_push_target_failed",
64656
- outcome: "failed",
64657
- aspAgentId,
64658
- deliveryId,
64659
- conversationId: result.conversationId,
64660
- reason: result.status
64661
- })
64662
- );
64663
- }
64664
- const summary = summarizeSubscriptionPush(results);
64665
- const summaryOutcome = summary.failedCount === 0 ? "success" : summary.sentCount > 0 ? "partial" : "failed";
64666
- logger.info(
64667
- LogEvent.SUBSCRIPTION_PUSH_SUMMARY,
64668
- buildSubscriptionSendExtras({
64669
- checkpoint: "outbound/subscription_push_summary",
64670
- outcome: summaryOutcome,
64671
- aspAgentId,
64672
- deliveryId,
64673
- targetCount: summary.conversationCount,
64674
- sentCount: summary.sentCount,
64675
- failedCount: summary.failedCount
64676
- })
64677
- );
64678
- return { ...summary, results };
64679
- }
64680
-
64681
64523
  // src/command-processor.ts
64682
64524
  init_session_store();
64683
64525
  init_ai_provider();
@@ -65358,9 +65200,6 @@ function commandSentryExtra(command, extra = {}) {
65358
65200
  base.myAgentId = command.myAgentId ?? "";
65359
65201
  base.toAgentId = command.toAgentId ?? "";
65360
65202
  base.toXmtpAddress = command.toXmtpAddress ?? "";
65361
- } else if (command.type === "xmtp-subscription-push") {
65362
- base.myAgentId = command.myAgentId;
65363
- base.conversationCount = command.conversationIds.length;
65364
65203
  } else if (command.type === "xmtp-deny-pending-conversation") {
65365
65204
  base.groupId = command.groupId;
65366
65205
  base.jobId = command.jobId ?? "";
@@ -65716,10 +65555,6 @@ async function handleDaemonCommand(command, params) {
65716
65555
  });
65717
65556
  return { ok: true, messageId: result.messageId };
65718
65557
  }
65719
- if (command.type === "xmtp-subscription-push") {
65720
- const result = await handleSubscriptionPushCommand({ command, service: params.service });
65721
- return { ok: true, payload: result };
65722
- }
65723
65558
  if (command.type === "xmtp-get-pending-list") {
65724
65559
  return { ok: true, payload: await listPendingTaskRequests(params) };
65725
65560
  }
@@ -65802,12 +65637,12 @@ async function listPendingTaskRequests(params) {
65802
65637
  }
65803
65638
  async function denyPendingConversationsByJobId(jobId, params, content) {
65804
65639
  const pending = await listPendingTaskRequests(params);
65805
- const matched = pending.filter((item) => isPlainObject3(item) && readString2(item.jobId) === jobId);
65640
+ const matched = pending.filter((item) => isPlainObject2(item) && readString2(item.jobId) === jobId);
65806
65641
  const clientAddresses = [...params.service.getClients().keys()];
65807
65642
  const targetsByKey = collectDenyTargetsFromPending(matched, clientAddresses);
65808
65643
  const groupIds = /* @__PURE__ */ new Set();
65809
65644
  for (const item of matched) {
65810
- if (!isPlainObject3(item)) {
65645
+ if (!isPlainObject2(item)) {
65811
65646
  continue;
65812
65647
  }
65813
65648
  const groupId = readString2(item.groupId);
@@ -65834,7 +65669,7 @@ async function denyPendingConversationsByJobId(jobId, params, content) {
65834
65669
  function collectDenyTargetsFromPending(pending, fallbackAddresses) {
65835
65670
  const targetsByKey = /* @__PURE__ */ new Map();
65836
65671
  for (const item of pending) {
65837
- if (!isPlainObject3(item)) {
65672
+ if (!isPlainObject2(item)) {
65838
65673
  continue;
65839
65674
  }
65840
65675
  const groupId = readString2(item.groupId);
@@ -65859,7 +65694,7 @@ ${groupId}`, {
65859
65694
  async function resolvePendingTargetsByGroupId(groupId, addresses, params) {
65860
65695
  const addressSet = addresses ? new Set(addresses) : null;
65861
65696
  const pending = (await listPendingTaskRequests(params)).filter((item) => {
65862
- if (!isPlainObject3(item) || readString2(item.groupId) !== groupId) {
65697
+ if (!isPlainObject2(item) || readString2(item.groupId) !== groupId) {
65863
65698
  return false;
65864
65699
  }
65865
65700
  const address = readString2(item.myXmtpAddress);
@@ -65979,7 +65814,7 @@ function filterKnownPendingGroups(items, sessionStore) {
65979
65814
  return items;
65980
65815
  }
65981
65816
  return items.filter((item) => {
65982
- if (!isPlainObject3(item)) {
65817
+ if (!isPlainObject2(item)) {
65983
65818
  return true;
65984
65819
  }
65985
65820
  const jobId = readString2(item.jobId);
@@ -65990,7 +65825,7 @@ function filterKnownPendingGroups(items, sessionStore) {
65990
65825
  return sessionStore.querySessions({ jobId, toAgentId, limit: 1 }).length === 0;
65991
65826
  });
65992
65827
  }
65993
- function isPlainObject3(value) {
65828
+ function isPlainObject2(value) {
65994
65829
  return !!value && typeof value === "object" && !Array.isArray(value);
65995
65830
  }
65996
65831
  function readString2(value) {
@@ -66124,10 +65959,6 @@ function formatCommandCompleted(command, result) {
66124
65959
  if (command.type === "xmtp-send") {
66125
65960
  return `[okx-agent-task] xmtp-send command completed id=${command.id} job=${command.jobId} messageId=${result.messageId}`;
66126
65961
  }
66127
- if (command.type === "xmtp-subscription-push") {
66128
- const payload = isPlainObject3(result.payload) ? result.payload : {};
66129
- return `[okx-agent-task] xmtp-subscription-push command completed id=${command.id} deliveryId=${command.deliveryId ?? "(none)"} conversationCount=${payload.conversationCount ?? 0} sentCount=${payload.sentCount ?? 0} failedCount=${payload.failedCount ?? 0}`;
66130
- }
66131
65962
  if (command.type === "xmtp-get-pending-list") {
66132
65963
  return `[okx-agent-task] xmtp-get-pending-list command completed id=${command.id}`;
66133
65964
  }
@@ -66148,8 +65979,8 @@ function formatCommandCompleted(command, result) {
66148
65979
  return `[okx-agent-task] xmtp-refresh-agents command completed id=${command.id}`;
66149
65980
  }
66150
65981
  function formatXmtpDebugCompleted(command, payload) {
66151
- const record = isPlainObject3(payload) ? payload : {};
66152
- const summary = isPlainObject3(record.summary) ? record.summary : {};
65982
+ const record = isPlainObject2(payload) ? payload : {};
65983
+ const summary = isPlainObject2(record.summary) ? record.summary : {};
66153
65984
  const count = command.action === "group-list" ? record.groupCount ?? 0 : command.action === "group-inspect" ? record.conversationFound ? 1 : 0 : summary.matchedCount ?? 0;
66154
65985
  return `[okx-agent-task] xmtp-debug command completed id=${command.id} action=${command.action} rows=${String(count)}`;
66155
65986
  }
@@ -66304,393 +66135,12 @@ function trimForUser2(value) {
66304
66135
 
66305
66136
  // src/message-handler.ts
66306
66137
  init_log();
66307
- var import_node_crypto13 = require("node:crypto");
66138
+ var import_node_crypto12 = require("node:crypto");
66308
66139
  init_sentry_logger();
66309
66140
  init_log_fields();
66310
66141
  init_paths();
66311
66142
  init_session_store();
66312
66143
  init_ai_provider();
66313
-
66314
- // src/subscription-inbound.ts
66315
- init_log();
66316
- function decideSubscriptionGate(input) {
66317
- if (!isSubscriptionEnvelope(input.payload)) {
66318
- return { kind: "not_subscription" };
66319
- }
66320
- if (input.chatType === "dm") {
66321
- return { kind: "drop", reason: "dm_subscription" };
66322
- }
66323
- if (input.chatType === "unknown") {
66324
- return { kind: "drop", reason: "unknown_conversation_subscription" };
66325
- }
66326
- const read = readSubscriptionEnvelope(input.payload);
66327
- if (!read.ok) {
66328
- return { kind: "drop", reason: "invalid_envelope", detail: read.reason };
66329
- }
66330
- if (!input.senderInboxId) {
66331
- return { kind: "drop", reason: "missing_sender_inbox_id" };
66332
- }
66333
- return { kind: "v2", envelope: read.envelope };
66334
- }
66335
- function partitionSubscriptionJobsByOwner(input) {
66336
- const owned = [];
66337
- for (const job of input.jobs) {
66338
- if (job.userAgentId === input.localAgentId) {
66339
- owned.push(job);
66340
- }
66341
- }
66342
- return {
66343
- owned,
66344
- returnedCount: input.jobs.length,
66345
- ownedCount: owned.length,
66346
- ignoredCount: input.jobs.length - owned.length
66347
- };
66348
- }
66349
- function normalizeSubscriptionJobs(input) {
66350
- const seen = /* @__PURE__ */ new Set();
66351
- const normalized = [];
66352
- for (const job of input.jobs) {
66353
- const dedupKey = `${job.jobId}|${job.userAgentId}|${job.aspAgentId}`;
66354
- if (seen.has(dedupKey)) {
66355
- continue;
66356
- }
66357
- seen.add(dedupKey);
66358
- normalized.push({
66359
- jobId: job.jobId,
66360
- userAgentId: job.userAgentId,
66361
- aspAgentId: job.aspAgentId,
66362
- msgType: SUBSCRIPTION_MESSAGE_TYPE,
66363
- content: input.envelope.content,
66364
- ...input.envelope.deliveryId ? { deliveryId: input.envelope.deliveryId } : {},
66365
- conversationId: input.conversationId,
66366
- senderInboxId: input.senderInboxId
66367
- });
66368
- }
66369
- return normalized;
66370
- }
66371
- function subscriptionIdempotencyKey(input) {
66372
- const messageDimension = input.deliveryId || input.messageId;
66373
- return `${input.myXmtpAddress}|${messageDimension}|${input.jobId}`;
66374
- }
66375
- var SUBSCRIPTION_TARGETS_MAX = 2e3;
66376
- var subscriptionTargets = /* @__PURE__ */ new Map();
66377
- function tryMarkSubscriptionTarget(key) {
66378
- if (subscriptionTargets.has(key)) {
66379
- return false;
66380
- }
66381
- subscriptionTargets.set(key, Date.now());
66382
- while (subscriptionTargets.size > SUBSCRIPTION_TARGETS_MAX) {
66383
- const oldest = subscriptionTargets.keys().next().value;
66384
- if (oldest === void 0) {
66385
- break;
66386
- }
66387
- subscriptionTargets.delete(oldest);
66388
- }
66389
- return true;
66390
- }
66391
- function resetSubscriptionTargetsForTests() {
66392
- subscriptionTargets.clear();
66393
- }
66394
- var SUBSCRIPTION_FANOUT_MAX = 250;
66395
- function redactSenderInboxId(senderInboxId, left = 8, right = 6) {
66396
- if (!senderInboxId) {
66397
- return "(none)";
66398
- }
66399
- if (senderInboxId.length <= left + right + 1) {
66400
- return senderInboxId;
66401
- }
66402
- return `${senderInboxId.slice(0, left)}\u2026${senderInboxId.slice(-right)}`;
66403
- }
66404
- async function fanOutSubscriptionJobs(input) {
66405
- const { jobs, myXmtpAddress, messageId, dispatch, concurrency } = input;
66406
- const total = jobs.length;
66407
- const capacityAnomaly = total > SUBSCRIPTION_FANOUT_MAX;
66408
- if (capacityAnomaly) {
66409
- logWithTimestamp(
66410
- `[okx-agent-task:${myXmtpAddress}] subscription fan-out capacity anomaly: jobs=${total} max=${SUBSCRIPTION_FANOUT_MAX} message=${messageId}`
66411
- );
66412
- }
66413
- const settled = await parallelMap(
66414
- jobs,
66415
- async (job) => {
66416
- const idempotencyKey = subscriptionIdempotencyKey({
66417
- myXmtpAddress,
66418
- deliveryId: job.deliveryId,
66419
- messageId,
66420
- jobId: job.jobId
66421
- });
66422
- if (subscriptionTargets.has(idempotencyKey)) {
66423
- return { key: idempotencyKey, outcome: "duplicate" };
66424
- }
66425
- const dispatchOutcome = await dispatch(job, idempotencyKey);
66426
- const isDurableDuplicate = !!dispatchOutcome && dispatchOutcome.created === false;
66427
- return { key: idempotencyKey, outcome: isDurableDuplicate ? "duplicate" : "started" };
66428
- },
66429
- concurrency ?? 20
66430
- );
66431
- let started = 0;
66432
- let failed = 0;
66433
- let skippedDuplicate = 0;
66434
- const results = [];
66435
- settled.forEach((result, idx) => {
66436
- const job = jobs[idx];
66437
- if (result.status === "rejected") {
66438
- failed += 1;
66439
- results.push({ jobId: job?.jobId ?? "(unknown)", outcome: "failed", error: result.reason });
66440
- logWithTimestamp(
66441
- `[okx-agent-task:${myXmtpAddress}] subscription dispatch failed message=${messageId} job=${job?.jobId ?? "(unknown)"} sender=${redactSenderInboxId(job?.senderInboxId)}:`,
66442
- result.reason
66443
- );
66444
- return;
66445
- }
66446
- tryMarkSubscriptionTarget(result.value.key);
66447
- if (result.value.outcome === "duplicate") {
66448
- skippedDuplicate += 1;
66449
- results.push({ jobId: job?.jobId ?? "(unknown)", outcome: "duplicate" });
66450
- } else {
66451
- started += 1;
66452
- results.push({ jobId: job?.jobId ?? "(unknown)", outcome: "started" });
66453
- }
66454
- });
66455
- return { total, started, failed, skippedDuplicate, capacityAnomaly, results };
66456
- }
66457
-
66458
- // ../core/src/xmtp-sdk/onchainos/list-jobs-by-verified-sender.ts
66459
- init_log();
66460
- init_sentry_logger();
66461
- function isPlainObject4(value) {
66462
- return !!value && typeof value === "object" && !Array.isArray(value);
66463
- }
66464
- function isNonEmptyString2(value) {
66465
- return typeof value === "string" && value.length > 0;
66466
- }
66467
- function redactLogValue(value, left = 6, right = 4) {
66468
- if (!value) {
66469
- return "(none)";
66470
- }
66471
- if (value.length <= left + right + 1) {
66472
- return "(redacted)";
66473
- }
66474
- return `${value.slice(0, left)}\u2026${value.slice(-right)}`;
66475
- }
66476
- function guardSessionExpired3(stdout, command) {
66477
- if (isSessionExpired(stdout)) {
66478
- reportSessionExpired(command);
66479
- }
66480
- }
66481
- function guardCatchSessionExpired3(err, command) {
66482
- const stdout = String(err?.stdout ?? "");
66483
- if (stdout && isSessionExpired(stdout)) {
66484
- reportSessionExpired(command);
66485
- }
66486
- }
66487
- function buildListJobsByVerifiedSenderArgs(params) {
66488
- return [
66489
- "agent",
66490
- "list-jobs-by-verified-sender",
66491
- "--group-id",
66492
- params.groupId,
66493
- "--sender-inbox-id",
66494
- params.senderInboxId,
66495
- "--agentic-id",
66496
- params.agenticId
66497
- ];
66498
- }
66499
- var KNOWN_ERROR_CODES2 = {
66500
- "130100079": "sender_not_authorized",
66501
- "130100073": "sender_not_eligible"
66502
- };
66503
- function extractErrorText(errorLike) {
66504
- if (typeof errorLike === "string") {
66505
- return errorLike;
66506
- }
66507
- if (typeof errorLike === "number") {
66508
- return String(errorLike);
66509
- }
66510
- if (errorLike && typeof errorLike === "object") {
66511
- const anyErr = errorLike;
66512
- return [anyErr.code, anyErr.message, anyErr.stdout, anyErr.stderr].filter((value) => typeof value === "string" || typeof value === "number").map(String).join(" ");
66513
- }
66514
- return errorLike == null ? "" : String(errorLike);
66515
- }
66516
- function classifyListJobsError(errorLike) {
66517
- const text = extractErrorText(errorLike);
66518
- for (const [code, reason] of Object.entries(KNOWN_ERROR_CODES2)) {
66519
- if (text.includes(code)) {
66520
- return { reason, errorCode: code };
66521
- }
66522
- }
66523
- if (/\b401\b/.test(text)) {
66524
- return { reason: "auth_error", errorCode: "401" };
66525
- }
66526
- if (/\b403\b/.test(text)) {
66527
- return { reason: "auth_error", errorCode: "403" };
66528
- }
66529
- return { reason: "invalid_response" };
66530
- }
66531
- function normalizeListJobsResponse(data) {
66532
- const rawJobs = isPlainObject4(data) && Array.isArray(data.jobs) ? data.jobs : [];
66533
- const seen = /* @__PURE__ */ new Set();
66534
- const jobs = [];
66535
- let invalidCount = 0;
66536
- for (const item of rawJobs) {
66537
- if (!isPlainObject4(item) || !isNonEmptyString2(item.jobId) || !isNonEmptyString2(item.userAgentId) || !isNonEmptyString2(item.aspAgentId)) {
66538
- invalidCount += 1;
66539
- continue;
66540
- }
66541
- const key = `${item.jobId}|${item.userAgentId}|${item.aspAgentId}`;
66542
- if (seen.has(key)) {
66543
- continue;
66544
- }
66545
- seen.add(key);
66546
- jobs.push({ jobId: item.jobId, userAgentId: item.userAgentId, aspAgentId: item.aspAgentId });
66547
- }
66548
- return { jobs, invalidCount };
66549
- }
66550
- async function listJobsByVerifiedSender(params, execFn = exec) {
66551
- logWithTimestamp(
66552
- `[onchainos] listing jobs by verified sender: group=${params.groupId} sender=${redactLogValue(params.senderInboxId)} agentic=${params.agenticId}`
66553
- );
66554
- let stdout;
66555
- let stderr;
66556
- try {
66557
- ({ stdout, stderr } = await execFn(buildListJobsByVerifiedSenderArgs(params)));
66558
- } catch (err) {
66559
- guardCatchSessionExpired3(err, "list-jobs-by-verified-sender");
66560
- const classified = classifyListJobsError(err);
66561
- const reason = classified.reason === "invalid_response" ? "network_error" : classified.reason;
66562
- warnWithTimestamp(
66563
- `[onchainos] list-jobs-by-verified-sender exec failed (group=${params.groupId} sender=${redactLogValue(params.senderInboxId)}); fail-closed reason=${reason}`
66564
- );
66565
- return { status: "fail_closed", jobs: [], invalidCount: 0, reason, errorCode: classified.errorCode };
66566
- }
66567
- if (stderr) {
66568
- logWithTimestamp(`[onchainos] stderr (list-jobs-by-verified-sender): ${stderr}`);
66569
- }
66570
- let res;
66571
- try {
66572
- res = parseCliJson(stdout, "list-jobs-by-verified-sender", {
66573
- groupId: params.groupId,
66574
- agenticId: params.agenticId
66575
- });
66576
- } catch {
66577
- return { status: "fail_closed", jobs: [], invalidCount: 0, reason: "invalid_response" };
66578
- }
66579
- if (!res.ok) {
66580
- guardSessionExpired3(stdout, "list-jobs-by-verified-sender");
66581
- const classified = classifyListJobsError(res.error);
66582
- warnWithTimestamp(
66583
- `[onchainos] list-jobs-by-verified-sender ok=false (group=${params.groupId}); fail-closed reason=${classified.reason}`
66584
- );
66585
- logger.error(
66586
- LogEvent.ONCHAINOS_CLI_ERROR,
66587
- new Error("list-jobs-by-verified-sender ok=false"),
66588
- cliOkFalseExtras(stdout, "list-jobs-by-verified-sender", {
66589
- groupId: params.groupId,
66590
- agenticId: params.agenticId,
66591
- reason: classified.reason
66592
- })
66593
- );
66594
- return { status: "fail_closed", jobs: [], invalidCount: 0, reason: classified.reason, errorCode: classified.errorCode };
66595
- }
66596
- const { jobs, invalidCount } = normalizeListJobsResponse(res.data);
66597
- if (jobs.length === 0) {
66598
- logWithTimestamp(
66599
- `[onchainos] list-jobs-by-verified-sender: empty (group=${params.groupId} invalidCount=${invalidCount})`
66600
- );
66601
- return { status: "empty", jobs, invalidCount };
66602
- }
66603
- logWithTimestamp(
66604
- `[onchainos] list-jobs-by-verified-sender: ok (group=${params.groupId} jobs=${jobs.length} invalidCount=${invalidCount})`
66605
- );
66606
- return { status: "ok", jobs, invalidCount };
66607
- }
66608
- var LIST_JOBS_BY_VERIFIED_SENDER_HELP_TOKEN = "list-jobs-by-verified-sender";
66609
- function listJobsByVerifiedSenderHelpAdvertisesCommand(helpText) {
66610
- if (typeof helpText !== "string" || helpText.length === 0) {
66611
- return false;
66612
- }
66613
- const lower = helpText.toLowerCase();
66614
- if (/unknown command|unrecognized|not a valid command|no such (sub)?command|command not found/.test(lower)) {
66615
- return false;
66616
- }
66617
- return lower.includes(LIST_JOBS_BY_VERIFIED_SENDER_HELP_TOKEN);
66618
- }
66619
- var CAPABILITY_UPGRADE_PAIR_KEY = "onchainos:list-jobs-by-verified-sender";
66620
- var CAPABILITY_UPGRADE_REASON = "OnchainOS does not support `agent list-jobs-by-verified-sender`; the V2 subscription shared-group inbound path is fail-closed until OnchainOS is upgraded. Upgrade the OnchainOS CLI, then re-run.";
66621
- var capabilityProbe2 = null;
66622
- var capabilityRecommendedPairs = /* @__PURE__ */ new Set();
66623
- function resetListJobsByVerifiedSenderCapabilityForTests() {
66624
- capabilityProbe2 = null;
66625
- capabilityRecommendedPairs.clear();
66626
- }
66627
- function maybeRecommendListJobsUpgrade(capability) {
66628
- if (capability.supported || capabilityRecommendedPairs.has(CAPABILITY_UPGRADE_PAIR_KEY)) {
66629
- return;
66630
- }
66631
- warnWithTimestamp(
66632
- `[onchainos] list-jobs-by-verified-sender unsupported (reason=${capability.reason}); ${CAPABILITY_UPGRADE_REASON}`
66633
- );
66634
- const hook = XmtpService.getInstance().tools?.notifyUpgradeRecommendation;
66635
- if (!hook) {
66636
- return;
66637
- }
66638
- capabilityRecommendedPairs.add(CAPABILITY_UPGRADE_PAIR_KEY);
66639
- try {
66640
- void Promise.resolve(
66641
- hook({
66642
- component: "onchainos",
66643
- capability: LIST_JOBS_BY_VERIFIED_SENDER_HELP_TOKEN,
66644
- reason: CAPABILITY_UPGRADE_REASON
66645
- })
66646
- ).catch((err) => {
66647
- warnWithTimestamp("[onchainos] list-jobs-by-verified-sender upgrade notice async delivery failed:", err);
66648
- });
66649
- } catch (err) {
66650
- warnWithTimestamp("[onchainos] list-jobs-by-verified-sender upgrade notice threw:", err);
66651
- }
66652
- }
66653
- function detectListJobsByVerifiedSenderSupport(execFn = exec) {
66654
- if (!capabilityProbe2) {
66655
- capabilityProbe2 = (async () => {
66656
- try {
66657
- const { stdout, stderr } = await execFn([
66658
- "agent",
66659
- "list-jobs-by-verified-sender",
66660
- "--help"
66661
- ]);
66662
- const supported = listJobsByVerifiedSenderHelpAdvertisesCommand(`${stdout}
66663
- ${stderr}`);
66664
- logWithTimestamp(
66665
- `[onchainos] list-jobs-by-verified-sender capability: ${supported ? "supported" : "unsupported_cli_capability"}`
66666
- );
66667
- return supported ? { supported: true } : { supported: false, reason: "unsupported_cli_capability" };
66668
- } catch (err) {
66669
- logWithTimestamp(
66670
- "[onchainos] list-jobs-by-verified-sender --help probe failed; treating as onchainos_upgrade_required:",
66671
- err
66672
- );
66673
- return { supported: false, reason: "onchainos_upgrade_required" };
66674
- }
66675
- })().then((capability) => {
66676
- maybeRecommendListJobsUpgrade(capability);
66677
- return capability;
66678
- });
66679
- }
66680
- return capabilityProbe2;
66681
- }
66682
- async function listJobsByVerifiedSenderWithCapability(params, execFn = exec) {
66683
- const capability = await detectListJobsByVerifiedSenderSupport(execFn);
66684
- if (!capability.supported) {
66685
- warnWithTimestamp(
66686
- `[onchainos] list-jobs-by-verified-sender skipped: CLI capability unavailable (reason=${capability.reason}) group=${params.groupId} sender=${redactLogValue(params.senderInboxId)}`
66687
- );
66688
- return { status: "fail_closed", jobs: [], invalidCount: 0, reason: capability.reason };
66689
- }
66690
- return listJobsByVerifiedSender(params, execFn);
66691
- }
66692
-
66693
- // src/message-handler.ts
66694
66144
  var PROCESSED_IDS_MAX = 1e3;
66695
66145
  var processedMessageIds = /* @__PURE__ */ new Map();
66696
66146
  function tryMarkProcessed(messageId) {
@@ -66707,7 +66157,7 @@ function tryMarkProcessed(messageId) {
66707
66157
  }
66708
66158
  return true;
66709
66159
  }
66710
- function isPlainObject5(value) {
66160
+ function isPlainObject3(value) {
66711
66161
  return !!value && typeof value === "object" && !Array.isArray(value);
66712
66162
  }
66713
66163
  function safeStringify(value) {
@@ -66768,9 +66218,9 @@ function readNumber(value) {
66768
66218
  }
66769
66219
  function resolveSessionAgentId(params) {
66770
66220
  const { chatType, payload, myXmtpAddress } = params;
66771
- const payloadObject = isPlainObject5(payload) ? payload : null;
66772
- const sender = isPlainObject5(payloadObject?.sender) ? payloadObject.sender : null;
66773
- const message = isPlainObject5(payloadObject?.message) ? payloadObject.message : null;
66221
+ const payloadObject = isPlainObject3(payload) ? payload : null;
66222
+ const sender = isPlainObject3(payloadObject?.sender) ? payloadObject.sender : null;
66223
+ const message = isPlainObject3(payloadObject?.message) ? payloadObject.message : null;
66774
66224
  const localAgentId = XmtpService.getInstance().getAgentByAddress(myXmtpAddress)?.agentId ?? null;
66775
66225
  if (chatType === "group") {
66776
66226
  return readString3(sender?.agentId) ?? readString3(payloadObject?.receiverAgentId) ?? localAgentId;
@@ -66781,7 +66231,7 @@ function resolveSessionAgentId(params) {
66781
66231
  return localAgentId;
66782
66232
  }
66783
66233
  function routeMessage(chatType, parsed, payload) {
66784
- if (!parsed || !isPlainObject5(payload)) {
66234
+ if (!parsed || !isPlainObject3(payload)) {
66785
66235
  return {
66786
66236
  jobId: BACKUP_JOB_ID,
66787
66237
  route: "backup",
@@ -66793,7 +66243,7 @@ function routeMessage(chatType, parsed, payload) {
66793
66243
  return jobId ? { jobId, route: "job", routeReason: "group-job-id" } : { jobId: BACKUP_JOB_ID, route: "backup", routeReason: "group-missing-job-id" };
66794
66244
  }
66795
66245
  if (chatType === "dm") {
66796
- const message = isPlainObject5(payload.message) ? payload.message : null;
66246
+ const message = isPlainObject3(payload.message) ? payload.message : null;
66797
66247
  const nestedJobId = readString3(message?.jobId);
66798
66248
  const directJobId = readString3(payload.jobId);
66799
66249
  const jobId = nestedJobId ?? directJobId;
@@ -66806,10 +66256,10 @@ function routeMessage(chatType, parsed, payload) {
66806
66256
  return { jobId: BACKUP_JOB_ID, route: "backup", routeReason: "unknown-conversation" };
66807
66257
  }
66808
66258
  function extractDirectToUserNotification(payload) {
66809
- if (!isPlainObject5(payload)) {
66259
+ if (!isPlainObject3(payload)) {
66810
66260
  return { kind: "none" };
66811
66261
  }
66812
- const message = isPlainObject5(payload.message) ? payload.message : null;
66262
+ const message = isPlainObject3(payload.message) ? payload.message : null;
66813
66263
  if (message?.isDirectToUser !== true) {
66814
66264
  return { kind: "none" };
66815
66265
  }
@@ -66833,10 +66283,10 @@ function extractDirectToUserNotification(payload) {
66833
66283
  };
66834
66284
  }
66835
66285
  function extractSystemNotification(payload) {
66836
- if (!isPlainObject5(payload)) {
66286
+ if (!isPlainObject3(payload)) {
66837
66287
  return null;
66838
66288
  }
66839
- const message = isPlainObject5(payload.message) ? payload.message : null;
66289
+ const message = isPlainObject3(payload.message) ? payload.message : null;
66840
66290
  const isDirectCommunication = message?.isDirectCommunication === true;
66841
66291
  if (message?.source !== "system" && !isDirectCommunication) {
66842
66292
  return null;
@@ -67071,7 +66521,7 @@ function inboundStageExtras(stage, outcome) {
67071
66521
  })
67072
66522
  };
67073
66523
  }
67074
- function definedExtras2(input) {
66524
+ function definedExtras(input) {
67075
66525
  return Object.entries(input).reduce((out, [key, value]) => {
67076
66526
  const text = readString3(value);
67077
66527
  if (text) {
@@ -67103,7 +66553,7 @@ function buildInboundTerminalExtras(input) {
67103
66553
  originPlatform: classifyOriginPlatform({ env: process.env }),
67104
66554
  deliveryId: resolveDeliveryId({ messageId, jobId, sessionKey })
67105
66555
  }),
67106
- ...definedExtras2({
66556
+ ...definedExtras({
67107
66557
  messageId,
67108
66558
  conversationId,
67109
66559
  chatType,
@@ -67137,7 +66587,7 @@ function maybeNotifyInboundAgentMessage(params) {
67137
66587
  return;
67138
66588
  }
67139
66589
  const content = payloadObject.content;
67140
- const sender = isPlainObject5(payloadObject.sender) ? payloadObject.sender : null;
66590
+ const sender = isPlainObject3(payloadObject.sender) ? payloadObject.sender : null;
67141
66591
  const localAgent = XmtpService.getInstance().getAgentByAddress(params.deps.myXmtpAddress);
67142
66592
  void notifyAgentMessageToUserAttention({
67143
66593
  direction: "inbound" /* INBOUND */,
@@ -67168,11 +66618,11 @@ function stringifySystemPayload(payload) {
67168
66618
  }
67169
66619
  }
67170
66620
  function summarizePayloadForLog(payload) {
67171
- if (!isPlainObject5(payload)) {
66621
+ if (!isPlainObject3(payload)) {
67172
66622
  return "payload=non-object";
67173
66623
  }
67174
- const message = isPlainObject5(payload.message) ? payload.message : null;
67175
- const sender = isPlainObject5(payload.sender) ? payload.sender : null;
66624
+ const message = isPlainObject3(payload.message) ? payload.message : null;
66625
+ const sender = isPlainObject3(payload.sender) ? payload.sender : null;
67176
66626
  const jobId = readString3(payload.jobId) ?? readString3(message?.jobId);
67177
66627
  const parts = [
67178
66628
  readString3(payload.msgType) ? `type=${readString3(payload.msgType)}` : null,
@@ -67441,7 +66891,7 @@ async function verifyInboundA2AGroupMessage(params) {
67441
66891
  messageId,
67442
66892
  groupId,
67443
66893
  jobId,
67444
- agentId: readString3(isPlainObject5(payload.sender) ? payload.sender.agentId : null),
66894
+ agentId: readString3(isPlainObject3(payload.sender) ? payload.sender.agentId : null),
67445
66895
  localAgentId: myAgent?.agentId ?? null,
67446
66896
  senderAddress,
67447
66897
  senderInboxId,
@@ -67467,7 +66917,7 @@ async function verifyInboundA2AGroupMessage(params) {
67467
66917
  });
67468
66918
  return false;
67469
66919
  }
67470
- const sender = isPlainObject5(payload.sender) ? payload.sender : null;
66920
+ const sender = isPlainObject3(payload.sender) ? payload.sender : null;
67471
66921
  const senderAgentId = readString3(sender?.agentId);
67472
66922
  const senderRole = readNumber(sender?.role);
67473
66923
  if (!senderAgentId || !myAgent) {
@@ -67636,302 +67086,9 @@ ${failureMessage}`,
67636
67086
  }
67637
67087
  return true;
67638
67088
  }
67639
- async function processSubscriptionInbound(ctx, deps, input) {
67640
- const { decision, conversationId, messageId } = input;
67641
- const senderInboxId = ctx.message.senderInboxId ?? "";
67642
- if (decision.kind === "drop") {
67643
- logger.info(
67644
- LogEvent.SUBSCRIPTION_INBOUND_GATE_DROPPED,
67645
- buildSubscriptionInboundExtras({
67646
- checkpoint: "inbound/subscription_gate_dropped",
67647
- outcome: "dropped",
67648
- conversationId,
67649
- messageId,
67650
- senderInboxId: shortenLogValue(senderInboxId),
67651
- reason: decision.reason
67652
- })
67653
- );
67654
- logWithTimestamp(
67655
- `[okx-agent-task:${deps.myXmtpAddress}] subscription message dropped reason=${decision.reason}${decision.detail ? ` detail=${decision.detail}` : ""} conv=${conversationId} message=${shortenLogValue(messageId)} sender=${shortenLogValue(senderInboxId)}`
67656
- );
67657
- return true;
67658
- }
67659
- if (decision.kind === "not_subscription") {
67660
- return true;
67661
- }
67662
- const { envelope } = decision;
67663
- const agenticId = XmtpService.getInstance().getAgentByAddress(deps.myXmtpAddress)?.agentId;
67664
- if (!agenticId) {
67665
- logWithTimestamp(
67666
- `[okx-agent-task:${deps.myXmtpAddress}] subscription fail-closed: no local agenticId for ${deps.myXmtpAddress}, conv=${conversationId} message=${shortenLogValue(messageId)}`
67667
- );
67668
- logger.error(
67669
- LogEvent.SUBSCRIPTION_INBOUND_AGENTIC_ID_MISSING,
67670
- new Error("Subscription inbound: local agenticId not resolved"),
67671
- buildSubscriptionInboundExtras({
67672
- checkpoint: "inbound/subscription_agentic_id",
67673
- outcome: "blocked",
67674
- conversationId,
67675
- messageId,
67676
- senderInboxId: shortenLogValue(senderInboxId),
67677
- reason: "missing_agentic_id"
67678
- })
67679
- );
67680
- return true;
67681
- }
67682
- logWithTimestamp(
67683
- `[okx-agent-task:${deps.myXmtpAddress}] subscription received msgType=${envelope.msgType} conv=${conversationId} message=${shortenLogValue(messageId)} sender=${shortenLogValue(senderInboxId)}`
67684
- );
67685
- logger.info(
67686
- LogEvent.SUBSCRIPTION_INBOUND_RECEIVED,
67687
- buildSubscriptionInboundExtras({
67688
- checkpoint: "inbound/subscription_received",
67689
- userAgentId: agenticId,
67690
- conversationId,
67691
- messageId,
67692
- deliveryId: envelope.deliveryId,
67693
- senderInboxId: shortenLogValue(senderInboxId)
67694
- })
67695
- );
67696
- const listJobs = deps.listJobsByVerifiedSenderImpl ?? listJobsByVerifiedSenderWithCapability;
67697
- logger.info(
67698
- LogEvent.SUBSCRIPTION_JOBS_QUERY_STARTED,
67699
- buildSubscriptionInboundExtras({
67700
- checkpoint: "inbound/subscription_jobs_query_started",
67701
- userAgentId: agenticId,
67702
- conversationId,
67703
- messageId
67704
- })
67705
- );
67706
- const listJobsResult = await listJobs({
67707
- groupId: conversationId,
67708
- senderInboxId,
67709
- agenticId
67710
- });
67711
- logWithTimestamp(
67712
- `[okx-agent-task:${deps.myXmtpAddress}] subscription queried status=${listJobsResult.status} jobs=${listJobsResult.jobs.length} invalid=${listJobsResult.invalidCount} conv=${conversationId} message=${shortenLogValue(messageId)}`
67713
- );
67714
- if (listJobsResult.status === "fail_closed") {
67715
- logger.error(
67716
- LogEvent.SUBSCRIPTION_JOBS_FAIL_CLOSED,
67717
- new Error("Subscription inbound: listJobsByVerifiedSender fail-closed"),
67718
- buildSubscriptionInboundExtras({
67719
- checkpoint: "inbound/subscription_jobs_fail_closed",
67720
- outcome: "blocked",
67721
- userAgentId: agenticId,
67722
- conversationId,
67723
- messageId,
67724
- senderInboxId: shortenLogValue(senderInboxId),
67725
- reason: listJobsResult.reason ?? "unknown",
67726
- errorCode: listJobsResult.errorCode
67727
- })
67728
- );
67729
- return true;
67730
- }
67731
- if (listJobsResult.status === "empty") {
67732
- logWithTimestamp(
67733
- `[okx-agent-task:${deps.myXmtpAddress}] subscription empty: no verified jobs for conv=${conversationId} message=${shortenLogValue(messageId)}`
67734
- );
67735
- logger.info(
67736
- LogEvent.SUBSCRIPTION_JOBS_EMPTY,
67737
- buildSubscriptionInboundExtras({
67738
- checkpoint: "inbound/subscription_jobs_empty",
67739
- outcome: "ignored",
67740
- userAgentId: agenticId,
67741
- conversationId,
67742
- messageId,
67743
- reason: "jobs_empty",
67744
- returnedCount: 0,
67745
- invalidCount: listJobsResult.invalidCount
67746
- })
67747
- );
67748
- return true;
67749
- }
67750
- logger.info(
67751
- LogEvent.SUBSCRIPTION_JOBS_QUERY_SUCCEEDED,
67752
- buildSubscriptionInboundExtras({
67753
- checkpoint: "inbound/subscription_jobs_query_succeeded",
67754
- userAgentId: agenticId,
67755
- conversationId,
67756
- messageId,
67757
- returnedCount: listJobsResult.jobs.length,
67758
- invalidCount: listJobsResult.invalidCount
67759
- })
67760
- );
67761
- const ownership = partitionSubscriptionJobsByOwner({
67762
- jobs: listJobsResult.jobs,
67763
- localAgentId: agenticId
67764
- });
67765
- logWithTimestamp(
67766
- `[okx-agent-task:${deps.myXmtpAddress}] subscription routed receiver=${agenticId} returned=${ownership.returnedCount} localOwned=${ownership.ownedCount} ignored=${ownership.ignoredCount} conv=${conversationId} message=${shortenLogValue(messageId)}`
67767
- );
67768
- logger.info(
67769
- LogEvent.SUBSCRIPTION_INBOUND_OWNERSHIP_ROUTED,
67770
- buildSubscriptionInboundExtras({
67771
- checkpoint: "inbound/subscription_ownership_routed",
67772
- outcome: ownership.ownedCount === 0 ? "ignored" : null,
67773
- userAgentId: agenticId,
67774
- conversationId,
67775
- messageId,
67776
- returnedCount: ownership.returnedCount,
67777
- ownedCount: ownership.ownedCount,
67778
- ignoredCount: ownership.ignoredCount
67779
- })
67780
- );
67781
- if (ownership.ownedCount === 0) {
67782
- return true;
67783
- }
67784
- const normalizedJobs = normalizeSubscriptionJobs({
67785
- jobs: ownership.owned,
67786
- envelope,
67787
- conversationId,
67788
- senderInboxId
67789
- });
67790
- logWithTimestamp(
67791
- `[okx-agent-task:${deps.myXmtpAddress}] subscription expanded jobs=${normalizedJobs.length} conv=${conversationId} message=${shortenLogValue(messageId)}`
67792
- );
67793
- let senderXmtpAddress = null;
67794
- try {
67795
- const resolved = await ctx.getSenderAddress();
67796
- senderXmtpAddress = resolved ? resolved : null;
67797
- } catch (err) {
67798
- logWithTimestamp(
67799
- `[okx-agent-task:${deps.myXmtpAddress}] subscription sender address unresolved (degrading to null) conv=${conversationId} message=${shortenLogValue(messageId)}:`,
67800
- err
67801
- );
67802
- }
67803
- const fanoutResult = await fanOutSubscriptionJobs({
67804
- jobs: normalizedJobs,
67805
- myXmtpAddress: deps.myXmtpAddress,
67806
- messageId,
67807
- dispatch: async (job, idempotencyKey) => {
67808
- const sessionKey = buildSessionKey({
67809
- jobId: job.jobId,
67810
- myAgentId: job.userAgentId,
67811
- toAgentId: job.aspAgentId
67812
- });
67813
- deps.sessionStore?.upsertSession({
67814
- sessionKey,
67815
- jobId: job.jobId,
67816
- myAgentId: job.userAgentId,
67817
- toAgentId: job.aspAgentId,
67818
- groupId: job.conversationId,
67819
- myAgentXmtpAddress: deps.myXmtpAddress,
67820
- toAgentXmtpAddress: senderXmtpAddress
67821
- });
67822
- return deps.onSessionMessage?.({
67823
- sessionKey,
67824
- content: JSON.stringify({
67825
- msgType: job.msgType,
67826
- content: job.content,
67827
- ...job.deliveryId ? { deliveryId: job.deliveryId } : {},
67828
- jobId: job.jobId,
67829
- userAgentId: job.userAgentId,
67830
- aspAgentId: job.aspAgentId,
67831
- conversationId: job.conversationId,
67832
- senderInboxId: job.senderInboxId,
67833
- // Raw XMTP messageId preserved for sender/receiver telemetry join;
67834
- // the durable dedup identity is the idempotencyKey passed as this
67835
- // session-message's own `messageId` field below (M1 fix).
67836
- xmtpMessageId: messageId
67837
- }),
67838
- messageId: idempotencyKey,
67839
- // Durable exactly-once enqueue key (M2): the wiring persists via
67840
- // CommandStore.submitIdempotent keyed on sessionKey+messageId so a
67841
- // re-processed / replayed message never creates a second command.
67842
- idempotencyKey,
67843
- jobId: job.jobId,
67844
- agentId: job.userAgentId
67845
- });
67846
- }
67847
- });
67848
- logWithTimestamp(
67849
- `[okx-agent-task:${deps.myXmtpAddress}] subscription fan-out succeeded=${fanoutResult.started} failed=${fanoutResult.failed} skippedDuplicate=${fanoutResult.skippedDuplicate} total=${fanoutResult.total} capacityAnomaly=${fanoutResult.capacityAnomaly} conv=${conversationId} message=${shortenLogValue(messageId)}`
67850
- );
67851
- const normalizedJobsById = new Map(normalizedJobs.map((job) => [job.jobId, job]));
67852
- for (const result of fanoutResult.results) {
67853
- const job = normalizedJobsById.get(result.jobId);
67854
- if (result.outcome === "started") {
67855
- logger.info(
67856
- LogEvent.SUBSCRIPTION_JOB_DISPATCHED,
67857
- buildSubscriptionJobExtras({
67858
- checkpoint: "dispatch/subscription_job_dispatched",
67859
- outcome: "success",
67860
- jobId: result.jobId,
67861
- userAgentId: agenticId,
67862
- aspAgentId: job?.aspAgentId,
67863
- conversationId,
67864
- deliveryId: envelope.deliveryId
67865
- })
67866
- );
67867
- } else if (result.outcome === "duplicate") {
67868
- logger.info(
67869
- LogEvent.SUBSCRIPTION_JOB_DUPLICATE_IGNORED,
67870
- buildSubscriptionJobExtras({
67871
- checkpoint: "dispatch/subscription_job_duplicate_ignored",
67872
- outcome: "ignored",
67873
- jobId: result.jobId,
67874
- userAgentId: agenticId,
67875
- aspAgentId: job?.aspAgentId,
67876
- conversationId,
67877
- deliveryId: envelope.deliveryId,
67878
- reason: "duplicate_delivery"
67879
- })
67880
- );
67881
- } else {
67882
- logger.error(
67883
- LogEvent.SUBSCRIPTION_JOB_FAILED,
67884
- toLoggableError(result.error),
67885
- buildSubscriptionJobExtras({
67886
- checkpoint: "dispatch/subscription_job_failed",
67887
- outcome: "failed",
67888
- jobId: result.jobId,
67889
- userAgentId: agenticId,
67890
- aspAgentId: job?.aspAgentId,
67891
- conversationId,
67892
- deliveryId: envelope.deliveryId,
67893
- reason: "session_dispatch_failed"
67894
- })
67895
- );
67896
- }
67897
- }
67898
- logger.info(
67899
- LogEvent.SUBSCRIPTION_FANOUT_SUMMARY,
67900
- buildSubscriptionJobExtras({
67901
- checkpoint: "dispatch/subscription_fanout_summary",
67902
- outcome: fanoutResult.failed === 0 ? "success" : fanoutResult.started > 0 || fanoutResult.skippedDuplicate > 0 ? "partial" : "failed",
67903
- conversationId,
67904
- userAgentId: agenticId,
67905
- total: fanoutResult.total,
67906
- started: fanoutResult.started,
67907
- failed: fanoutResult.failed,
67908
- skippedDuplicate: fanoutResult.skippedDuplicate
67909
- })
67910
- );
67911
- return true;
67912
- }
67913
67089
  async function processFileMessage(ctx, deps, options = {}) {
67914
67090
  const messageId = ctx.message.id ?? "";
67915
67091
  const timing = createInboundTimingTracker(extractXmtpSentAtMs2(ctx.message));
67916
- const subscriptionPrecheckRawText = extractRawText(ctx.message.content);
67917
- const subscriptionPrecheckParse = parseJson2(subscriptionPrecheckRawText);
67918
- if (subscriptionPrecheckParse.ok && isSubscriptionEnvelope(subscriptionPrecheckParse.data)) {
67919
- const { chatType: subscriptionChatType, conversationId: subscriptionConversationId } = getConversationInfo(ctx.conversation);
67920
- const gateDecision = decideSubscriptionGate({
67921
- // getConversationInfo's declared StoredChatType also lists "system",
67922
- // but that value is only ever produced for stored-message bookkeeping
67923
- // elsewhere in this file — the conversation-type branch above never
67924
- // returns it, so this narrowing is safe.
67925
- chatType: subscriptionChatType === "system" ? "unknown" : subscriptionChatType,
67926
- payload: subscriptionPrecheckParse.data,
67927
- senderInboxId: ctx.message.senderInboxId ?? ""
67928
- });
67929
- return processSubscriptionInbound(ctx, deps, {
67930
- decision: gateDecision,
67931
- conversationId: subscriptionConversationId,
67932
- messageId: messageId || `subscription-${(0, import_node_crypto13.randomUUID)()}`
67933
- });
67934
- }
67935
67092
  if (messageId && !tryMarkProcessed(messageId)) {
67936
67093
  logWithTimestamp(`[okx-agent-task:${deps.myXmtpAddress}] duplicate message ignored: ${messageId}`);
67937
67094
  logger.info(LogEvent.INBOUND_IGNORED_DUPLICATE, timing.extras({
@@ -67954,6 +67111,19 @@ async function processFileMessage(ctx, deps, options = {}) {
67954
67111
  chatType,
67955
67112
  ...extra
67956
67113
  });
67114
+ if (chatType === "dm") {
67115
+ const dmTrustStartedAt = Date.now();
67116
+ const trusted = await isTrustedDmSender({
67117
+ myXmtpAddress: deps.myXmtpAddress,
67118
+ senderInboxId: ctx.message.senderInboxId ?? "",
67119
+ messageId,
67120
+ conversationId
67121
+ });
67122
+ timing.mark("dmTrustCheck", dmTrustStartedAt);
67123
+ if (!trusted) {
67124
+ return true;
67125
+ }
67126
+ }
67957
67127
  const parseStartedAt = Date.now();
67958
67128
  const receivedRawText = extractRawText(ctx.message.content);
67959
67129
  const parseResult = parseJson2(receivedRawText);
@@ -67969,26 +67139,9 @@ async function processFileMessage(ctx, deps, options = {}) {
67969
67139
  }
67970
67140
  }
67971
67141
  timing.mark("payloadParse", parseStartedAt);
67972
- const parsedDmData = parseResult.ok ? parseResult.data : null;
67973
- const parsedDmMessage = isPlainObject5(parsedDmData) && isPlainObject5(parsedDmData.message) ? parsedDmData.message : null;
67974
- const dmCarriesSystemMarkers = parsedDmMessage?.isDirectToUser === true || parsedDmMessage?.source === "system" || parsedDmMessage?.isDirectCommunication === true;
67975
- const isA2ADm = chatType === "dm" && parseResult.ok && isA2AEnvelope(parseResult.data) && !dmCarriesSystemMarkers;
67976
- if (chatType === "dm" && !isA2ADm) {
67977
- const dmTrustStartedAt = Date.now();
67978
- const trusted = await isTrustedDmSender({
67979
- myXmtpAddress: deps.myXmtpAddress,
67980
- senderInboxId: ctx.message.senderInboxId ?? "",
67981
- messageId,
67982
- conversationId
67983
- });
67984
- timing.mark("dmTrustCheck", dmTrustStartedAt);
67985
- if (!trusted) {
67986
- return true;
67987
- }
67988
- }
67989
67142
  const directToUser = chatType === "dm" && parseResult.ok ? extractDirectToUserNotification(parseResult.data) : { kind: "none" };
67990
67143
  if (directToUser.kind === "invalid") {
67991
- const droppedMessageId = messageId || `direct-to-user-${(0, import_node_crypto13.randomUUID)()}`;
67144
+ const droppedMessageId = messageId || `direct-to-user-${(0, import_node_crypto12.randomUUID)()}`;
67992
67145
  logger.error(
67993
67146
  LogEvent.INBOUND_DROP_DM_INVALID_PAYLOAD,
67994
67147
  new Error("Invalid direct-to-user system DM"),
@@ -68012,7 +67165,7 @@ async function processFileMessage(ctx, deps, options = {}) {
68012
67165
  await dispatchDirectToUserNotification({
68013
67166
  deps,
68014
67167
  notification: directToUser.notification,
68015
- messageId: messageId || `direct-to-user-${(0, import_node_crypto13.randomUUID)()}`,
67168
+ messageId: messageId || `direct-to-user-${(0, import_node_crypto12.randomUUID)()}`,
68016
67169
  timing,
68017
67170
  source: options.source ?? "live"
68018
67171
  });
@@ -68020,7 +67173,7 @@ async function processFileMessage(ctx, deps, options = {}) {
68020
67173
  }
68021
67174
  const systemNotification = chatType === "dm" && parseResult.ok ? extractSystemNotification(parseResult.data) : null;
68022
67175
  if (systemNotification) {
68023
- const systemMessageId = messageId || `system-${(0, import_node_crypto13.randomUUID)()}`;
67176
+ const systemMessageId = messageId || `system-${(0, import_node_crypto12.randomUUID)()}`;
68024
67177
  logWithTimestamp(
68025
67178
  `[okx-agent-task:${deps.myXmtpAddress}] xmtp_system_message_received agentId=${systemNotification.agentId ?? ""} msg=${shortenLogValue(systemMessageId)} event=${systemNotification.event ?? ""} job=${shortenLogValue(systemNotification.jobId)} conv=${conversationId} source=${options.source ?? "live"} rawBytes=${Buffer.byteLength(rawText, "utf8")} rawPreview=${previewRawEnvelope(rawText)}`
68026
67179
  );
@@ -68181,7 +67334,7 @@ async function processFileMessage(ctx, deps, options = {}) {
68181
67334
  timing.mark("routeResolve", routeStartedAt);
68182
67335
  if (route.route === "job" && parseResult.ok && isA2AEnvelope(parseResult.data) && !isValidExternalJobId(route.jobId)) {
68183
67336
  const payloadObject = parseResult.data;
68184
- const sender = isPlainObject5(payloadObject.sender) ? payloadObject.sender : null;
67337
+ const sender = isPlainObject3(payloadObject.sender) ? payloadObject.sender : null;
68185
67338
  logWithTimestamp(
68186
67339
  `[okx-agent-task:${deps.myXmtpAddress}] inbound A2A message has invalid jobId, dropping: jobLength=${route.jobId.length} group=${conversationId}`
68187
67340
  );
@@ -68210,32 +67363,7 @@ async function processFileMessage(ctx, deps, options = {}) {
68210
67363
  });
68211
67364
  return true;
68212
67365
  }
68213
- if (isA2ADm && route.route !== "job") {
68214
- const payloadObject = parseResult.data;
68215
- const sender = isPlainObject5(payloadObject.sender) ? payloadObject.sender : null;
68216
- recordInvalidXmtpMessageBestEffort({
68217
- messageId,
68218
- groupId: conversationId,
68219
- jobId: null,
68220
- agentId: readString3(sender?.agentId),
68221
- localAgentId: XmtpService.getInstance().getAgentByAddress(deps.myXmtpAddress)?.agentId ?? null,
68222
- senderInboxId: ctx.message.senderInboxId ?? "",
68223
- reason: "dm_a2a_missing_job_id",
68224
- stage: "inbound/job_id_validation",
68225
- logTag: `[okx-agent-task:${deps.myXmtpAddress}]`
68226
- });
68227
- logger.info(LogEvent.INBOUND_DROP_INVALID_JOBID, {
68228
- ...agentExtras({ walletAddress: deps.myXmtpAddress }),
68229
- conversationId,
68230
- messageId,
68231
- chatType,
68232
- peerInboxId: ctx.message.senderInboxId ?? "",
68233
- ...inboundStageExtras("inbound/job_id_validation", "dropped"),
68234
- reason: "dm_a2a_missing_job_id"
68235
- });
68236
- return true;
68237
- }
68238
- if (route.route === "job" && chatType !== "group" && !isA2ADm) {
67366
+ if (route.route === "job" && chatType !== "group") {
68239
67367
  const providerBindStartedAt = Date.now();
68240
67368
  const providerGate = await bindMessageJobProviderToCurrentDefault(deps, route.jobId, "inbound-xmtp");
68241
67369
  timing.mark("providerBind", providerBindStartedAt);
@@ -68275,7 +67403,7 @@ async function processFileMessage(ctx, deps, options = {}) {
68275
67403
  );
68276
67404
  }
68277
67405
  if (route.route === "job" && chatType === "group") {
68278
- const payloadObject = isPlainObject5(parseResult.ok ? parseResult.data : null) ? parseResult.data : null;
67406
+ const payloadObject = isPlainObject3(parseResult.ok ? parseResult.data : null) ? parseResult.data : null;
68279
67407
  const service = XmtpService.getInstance();
68280
67408
  const trustedSystemSender = service.isTrustedSystemAccountSender({
68281
67409
  senderAddress,
@@ -68301,7 +67429,7 @@ async function processFileMessage(ctx, deps, options = {}) {
68301
67429
  });
68302
67430
  return true;
68303
67431
  }
68304
- const sender = isPlainObject5(payloadObject?.sender) ? payloadObject.sender : null;
67432
+ const sender = isPlainObject3(payloadObject?.sender) ? payloadObject.sender : null;
68305
67433
  const localAgent = service.getAgentByAddress(deps.myXmtpAddress);
68306
67434
  const myAgentId = localAgent?.agentId ?? readString3(payloadObject?.receiverAgentId) ?? sessionAgentId ?? null;
68307
67435
  const toAgentId = readString3(sender?.agentId);
@@ -68341,7 +67469,7 @@ async function processFileMessage(ctx, deps, options = {}) {
68341
67469
  }));
68342
67470
  return true;
68343
67471
  }
68344
- const routedMessageId = messageId || `group-${(0, import_node_crypto13.randomUUID)()}`;
67472
+ const routedMessageId = messageId || `group-${(0, import_node_crypto12.randomUUID)()}`;
68345
67473
  const sessionKey = ensureInboundGroupSession(deps, {
68346
67474
  jobId: route.jobId,
68347
67475
  myAgentId,
@@ -68406,102 +67534,8 @@ async function processFileMessage(ctx, deps, options = {}) {
68406
67534
  );
68407
67535
  return true;
68408
67536
  }
68409
- if (route.route === "job" && isA2ADm) {
68410
- const payloadObject = parseResult.data;
68411
- const accepted = await verifyInboundA2AGroupMessage({
68412
- payload: parseResult.data,
68413
- myXmtpAddress: deps.myXmtpAddress,
68414
- senderAddress,
68415
- senderInboxId: ctx.message.senderInboxId ?? "",
68416
- jobId: route.jobId,
68417
- groupId: conversationId,
68418
- messageId,
68419
- consentState: void 0,
68420
- trustedSystemSender: false,
68421
- isOfflineReplay: options.isOfflineReplay ?? false,
68422
- timing
68423
- });
68424
- if (!accepted) {
68425
- return true;
68426
- }
68427
- const providerBindStartedAt = Date.now();
68428
- const providerGate = await bindMessageJobProviderToCurrentDefault(deps, route.jobId, "inbound-xmtp");
68429
- timing.mark("providerBind", providerBindStartedAt);
68430
- if (!providerGate.allowed) {
68431
- logger.info(LogEvent.INBOUND_IGNORED_NON_BUSINESS, timing.extras({
68432
- ...buildInboundTerminalExtras({
68433
- terminalState: "provider_gate_denied",
68434
- myXmtpAddress: deps.myXmtpAddress,
68435
- messageId,
68436
- conversationId,
68437
- chatType,
68438
- jobId: route.jobId,
68439
- route: route.route,
68440
- reason: "job_provider_gate_denied"
68441
- }),
68442
- routeReason: route.routeReason,
68443
- providerBinding: providerGate.provider ?? ""
68444
- }));
68445
- return true;
68446
- }
68447
- const myAgentId = XmtpService.getInstance().getAgentByAddress(deps.myXmtpAddress)?.agentId ?? readString3(payloadObject.receiverAgentId) ?? sessionAgentId ?? null;
68448
- const sender = isPlainObject5(payloadObject.sender) ? payloadObject.sender : null;
68449
- const toAgentId = readString3(sender?.agentId);
68450
- const routedMessageId = messageId || `dm-${(0, import_node_crypto13.randomUUID)()}`;
68451
- const sessionKey = ensureInboundGroupSession(deps, {
68452
- jobId: route.jobId,
68453
- myAgentId,
68454
- toAgentId,
68455
- groupId: null,
68456
- toAgentXmtpAddress: senderAddress || readString3(payloadObject.fromXmtpAddress)
68457
- });
68458
- const dispatchStartedAt = Date.now();
68459
- void Promise.resolve(deps.onSessionMessage?.({
68460
- sessionKey,
68461
- content: rawText,
68462
- messageId: routedMessageId,
68463
- jobId: route.jobId,
68464
- agentId: myAgentId
68465
- })).then(() => {
68466
- timing.mark("sessionDispatch", dispatchStartedAt);
68467
- logger.info(LogEvent.INBOUND_DELIVERED, commonDeliveryExtras({
68468
- taskId: route.jobId,
68469
- agentId: myAgentId ?? "",
68470
- peerWalletAddress: senderAddress,
68471
- peerInboxId: ctx.message.senderInboxId ?? "",
68472
- peerAgentId: toAgentId ?? "",
68473
- sessionKey,
68474
- messageId: routedMessageId,
68475
- route: "dm",
68476
- ...inboundStageExtras("inbound/dm_session_dispatch", "success"),
68477
- dispatchTarget: deps.onSessionMessage ? "session" : "none"
68478
- }));
68479
- }).catch((err) => {
68480
- logWithTimestamp(`[okx-agent-task:${deps.myXmtpAddress}] onSessionMessage failed:`, err);
68481
- logger.error(LogEvent.INBOUND_DISPATCH_FAILED, toLoggableError(err), timing.extras({
68482
- ...buildInboundTerminalExtras({
68483
- terminalState: "dispatch_failed",
68484
- myXmtpAddress: deps.myXmtpAddress,
68485
- messageId: routedMessageId,
68486
- conversationId,
68487
- chatType,
68488
- jobId: route.jobId,
68489
- sessionKey,
68490
- route: "dm",
68491
- reason: "session_dispatch_failed"
68492
- }),
68493
- checkpoint: "inbound/dm_session_dispatch_failed",
68494
- agentId: myAgentId ?? "",
68495
- peerAgentId: toAgentId ?? ""
68496
- }));
68497
- });
68498
- logWithTimestamp(
68499
- `[okx-agent-task:${deps.myXmtpAddress}] session dispatch queued route=dm session=${sessionKey} message=${shortenLogValue(routedMessageId)} ${summarizePayloadForLog(parseResult.data)}`
68500
- );
68501
- return true;
68502
- }
68503
67537
  const stored = {
68504
- id: messageId || `local-${(0, import_node_crypto13.randomUUID)()}`,
67538
+ id: messageId || `local-${(0, import_node_crypto12.randomUUID)()}`,
68505
67539
  direction: "inbound",
68506
67540
  route: route.route,
68507
67541
  routeReason: route.routeReason,
@@ -68519,8 +67553,8 @@ async function processFileMessage(ctx, deps, options = {}) {
68519
67553
  await deps.store.append(route.jobId, stored, sessionAgentId);
68520
67554
  timing.mark("storeAppend", storeAppendStartedAt);
68521
67555
  if ((route.route === "job" || parseResult.ok && !isA2AEnvelope(stored.payload)) && !options.skipNotify) {
68522
- const payloadObject = isPlainObject5(stored.payload) ? stored.payload : null;
68523
- const sender = isPlainObject5(payloadObject?.sender) ? payloadObject.sender : null;
67556
+ const payloadObject = isPlainObject3(stored.payload) ? stored.payload : null;
67557
+ const sender = isPlainObject3(payloadObject?.sender) ? payloadObject.sender : null;
68524
67558
  const localAgent = XmtpService.getInstance().getAgentByAddress(deps.myXmtpAddress);
68525
67559
  const sessionKey = route.route === "job" ? buildSessionKey({
68526
67560
  jobId: route.jobId,
@@ -68538,8 +67572,8 @@ async function processFileMessage(ctx, deps, options = {}) {
68538
67572
  });
68539
67573
  }
68540
67574
  if (route.route === "job" && chatType === "group" && conversationId && senderAddress) {
68541
- const payloadObject = isPlainObject5(stored.payload) ? stored.payload : null;
68542
- const sender = isPlainObject5(payloadObject?.sender) ? payloadObject.sender : null;
67575
+ const payloadObject = isPlainObject3(stored.payload) ? stored.payload : null;
67576
+ const sender = isPlainObject3(payloadObject?.sender) ? payloadObject.sender : null;
68543
67577
  await deps.store.updateXmtpSession(route.jobId, {
68544
67578
  xmtpGroupId: conversationId,
68545
67579
  myXmtpAddress: deps.myXmtpAddress,
@@ -68682,7 +67716,7 @@ function processOfflineFromCoreDeps(store, ctx, deps, options) {
68682
67716
  function buildSystemStoredMessage(params) {
68683
67717
  const now = Date.now();
68684
67718
  return {
68685
- id: params.id ?? `system-${now}-${(0, import_node_crypto13.randomUUID)()}`,
67719
+ id: params.id ?? `system-${now}-${(0, import_node_crypto12.randomUUID)()}`,
68686
67720
  direction: "system",
68687
67721
  route: "backup",
68688
67722
  routeReason: params.reason,
@@ -68698,7 +67732,7 @@ function buildSystemStoredMessage(params) {
68698
67732
  };
68699
67733
  }
68700
67734
  function isA2AEnvelope(payload) {
68701
- return isPlainObject5(payload) && payload.msgType === A2A_MESSAGE_TYPE;
67735
+ return isPlainObject3(payload) && payload.msgType === A2A_MESSAGE_TYPE;
68702
67736
  }
68703
67737
 
68704
67738
  // src/listener.ts
@@ -68826,7 +67860,7 @@ async function enqueueAiJobMessageDispatch(params) {
68826
67860
  await commands.submit(command);
68827
67861
  return command;
68828
67862
  }
68829
- async function enqueueAiSessionMessageDispatchIdempotent(params) {
67863
+ async function enqueueAiSessionMessageDispatch(params) {
68830
67864
  const commands = params.commands ?? new CommandStore(params.homeDir);
68831
67865
  const messageId = params.event.messageId ?? `session-${Date.now()}`;
68832
67866
  const command = commands.createAiSessionMessageDispatchCommand({
@@ -68836,25 +67870,15 @@ async function enqueueAiSessionMessageDispatchIdempotent(params) {
68836
67870
  jobId: params.event.jobId,
68837
67871
  agentId: params.event.agentId
68838
67872
  });
68839
- const idempotencyKey = params.event.idempotencyKey?.trim();
68840
- if (idempotencyKey) {
68841
- const dbKey = `${command.sessionKey}
68842
- ${command.messageId}`;
68843
- const result = await commands.submitIdempotent(command, dbKey);
68844
- return {
68845
- command: result.created ? command : { ...command, id: result.commandId },
68846
- created: result.created
68847
- };
68848
- }
68849
67873
  await commands.submit(command);
68850
- return { command, created: true };
67874
+ return command;
68851
67875
  }
68852
67876
 
68853
67877
  // src/listener.ts
68854
67878
  init_paths();
68855
67879
 
68856
67880
  // src/user-attention-watchers.ts
68857
- var import_node_crypto14 = require("node:crypto");
67881
+ var import_node_crypto13 = require("node:crypto");
68858
67882
  init_sentry_logger();
68859
67883
  var USER_ATTENTION_WATCH_REPLACED_MESSAGE = "Another okx-a2a user watch with the same job scope was started, so this watcher has been closed. Do not run this watch command again automatically, because starting another watcher may interrupt a different session that is already monitoring task progress.";
68860
67884
  var USER_ATTENTION_WATCHER_SCAN_MS = 500;
@@ -68897,7 +67921,7 @@ function isOriginalParentProcessAlive(options) {
68897
67921
  }
68898
67922
  function registerUserAttentionWatcher(options) {
68899
67923
  return options.store.registerUserAttentionWatcher({
68900
- id: options.id ?? (0, import_node_crypto14.randomUUID)(),
67924
+ id: options.id ?? (0, import_node_crypto13.randomUUID)(),
68901
67925
  provider: options.provider,
68902
67926
  jobId: options.jobId,
68903
67927
  nowMs: options.nowMs ?? Date.now(),
@@ -69189,35 +68213,6 @@ var ListenerMaintenanceGate = class {
69189
68213
  }
69190
68214
  };
69191
68215
  var UPGRADE_RECOMMENDATION_IDEMPOTENCY_KEY = "system:onchainos-offline-replay-upgrade";
69192
- var LIST_JOBS_UPGRADE_RECOMMENDATION_IDEMPOTENCY_KEY = "system:onchainos-list-jobs-by-verified-sender-upgrade";
69193
- function buildUpgradeRecommendationNotice(input) {
69194
- const capability = input.capability?.trim() ?? "";
69195
- if (capability === MESSAGE_ELIGIBLE_OFFLINE_REPLAY_HELP_TOKEN) {
69196
- return {
69197
- title: "OnchainOS upgrade recommended",
69198
- content: "The installed OnchainOS version does not support offline-replay preferences. Subscription messages will continue to replay normally. Upgrade OnchainOS to enable this capability.\n\nSuggested command: onchainos upgrade",
69199
- idempotencyKey: UPGRADE_RECOMMENDATION_IDEMPOTENCY_KEY
69200
- };
69201
- }
69202
- if (capability === LIST_JOBS_BY_VERIFIED_SENDER_HELP_TOKEN) {
69203
- return {
69204
- title: "OnchainOS upgrade required for Subscription Shared Group",
69205
- content: "The installed OnchainOS version does not support the verified-sender task query required by Subscription Shared Group. Until OnchainOS is upgraded, Subscription Shared Group messages fail closed and are NOT routed to an AI Session. Upgrade OnchainOS to enable this capability.\n\nSuggested command: onchainos upgrade",
69206
- idempotencyKey: LIST_JOBS_UPGRADE_RECOMMENDATION_IDEMPOTENCY_KEY
69207
- };
69208
- }
69209
- const capabilitySlug = capability ? capability.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") : "";
69210
- const idempotencyKey = capabilitySlug ? `system:onchainos-${capabilitySlug}-upgrade` : "system:onchainos-capability-upgrade";
69211
- const capabilityLabel = capability || "a required capability";
69212
- const reasonSuffix = input.reason?.trim() ? ` ${input.reason.trim()}` : "";
69213
- return {
69214
- title: "OnchainOS upgrade recommended",
69215
- content: `The installed OnchainOS version does not support ${capabilityLabel}.${reasonSuffix} Upgrade OnchainOS to enable this capability.
69216
-
69217
- Suggested command: onchainos upgrade`,
69218
- idempotencyKey
69219
- };
69220
- }
69221
68216
  function resolveOfflineReplayIntervalSec(systemConfig) {
69222
68217
  const interval = systemConfig.offlineReplayInterval;
69223
68218
  if (typeof interval !== "number" || !Number.isFinite(interval) || interval <= 0) {
@@ -69446,12 +68441,8 @@ async function runListenerWithLock(options, paths) {
69446
68441
  onJobMessageStored: async (event) => {
69447
68442
  await enqueueAiJobMessageDispatch({ commands, event });
69448
68443
  },
69449
- // Returns { created } so the V2 subscription fan-out can distinguish a
69450
- // durable DB duplicate (idempotent success) from a fresh enqueue. V1
69451
- // group/system callers ignore the return; their events carry no
69452
- // idempotencyKey, so the plain submit path (unchanged) is used.
69453
68444
  onSessionMessage: async (event) => {
69454
- return enqueueAiSessionMessageDispatchIdempotent({ commands, event });
68445
+ await enqueueAiSessionMessageDispatch({ commands, event });
69455
68446
  }
69456
68447
  }),
69457
68448
  processOfflineMessage: (ctx, deps, replayOptions) => processOfflineFromCoreDeps(store, ctx, deps, {
@@ -69461,7 +68452,7 @@ async function runListenerWithLock(options, paths) {
69461
68452
  await enqueueAiJobMessageDispatch({ commands, event });
69462
68453
  },
69463
68454
  onSessionMessage: async (event) => {
69464
- return enqueueAiSessionMessageDispatchIdempotent({ commands, event });
68455
+ await enqueueAiSessionMessageDispatch({ commands, event });
69465
68456
  }
69466
68457
  }),
69467
68458
  notifySessionExpired: (command) => {
@@ -69479,12 +68470,12 @@ async function runListenerWithLock(options, paths) {
69479
68470
  });
69480
68471
  },
69481
68472
  notifyUpgradeRecommendation: (input) => {
69482
- const notice = buildUpgradeRecommendationNotice(input);
68473
+ const content = "The installed OnchainOS version does not support offline-replay preferences. Subscription messages will continue to replay normally. Upgrade OnchainOS to enable this capability.\n\nSuggested command: onchainos upgrade";
69483
68474
  void notifySystemMessageToUser({
69484
- title: notice.title,
69485
- content: notice.content,
68475
+ title: "OnchainOS upgrade recommended",
68476
+ content,
69486
68477
  store: sessionStore,
69487
- idempotencyKey: notice.idempotencyKey
68478
+ idempotencyKey: UPGRADE_RECOMMENDATION_IDEMPOTENCY_KEY
69488
68479
  }).catch((err) => {
69489
68480
  logWithTimestamp(
69490
68481
  `[okx-agent-task] upgrade recommendation notify failed component=${input.component} capability=${input.capability}:`,
@@ -69493,12 +68484,12 @@ async function runListenerWithLock(options, paths) {
69493
68484
  });
69494
68485
  }
69495
68486
  });
69496
- service.setPluginVersion("0.2.18-beta-4dd056b897-261015113839");
68487
+ service.setPluginVersion("0.2.18");
69497
68488
  await service.init();
69498
68489
  const pluginVersionStatus = service.pluginVersionStatus;
69499
68490
  if (pluginVersionStatus.unavailable) {
69500
68491
  throw new Error(
69501
- `@okxweb3/a2a-node v${"0.2.18-beta-4dd056b897-261015113839"} is below the required minimum v${pluginVersionStatus.minVersion}`
68492
+ `@okxweb3/a2a-node v${"0.2.18"} is below the required minimum v${pluginVersionStatus.minVersion}`
69502
68493
  );
69503
68494
  }
69504
68495
  const systemConfig = service.getSystemConfig();
@@ -69526,7 +68517,7 @@ async function runListenerWithLock(options, paths) {
69526
68517
  onchainosAgentId: "*",
69527
68518
  reason: "system-config missing sentryDsn",
69528
68519
  pluginId: "@okxweb3/a2a-node",
69529
- pluginVersion: "0.2.18-beta-4dd056b897-261015113839"
68520
+ pluginVersion: "0.2.18"
69530
68521
  });
69531
68522
  }
69532
68523
  logWithTimestamp(
@@ -70988,7 +69979,7 @@ var import_node_path34 = require("node:path");
70988
69979
  var import_jszip = __toESM(require_lib3());
70989
69980
 
70990
69981
  // src/logs-export-archive.ts
70991
- var import_node_crypto15 = require("node:crypto");
69982
+ var import_node_crypto14 = require("node:crypto");
70992
69983
  var import_node_fs24 = require("node:fs");
70993
69984
  var import_promises13 = require("node:fs/promises");
70994
69985
  var import_node_path31 = require("node:path");
@@ -71624,7 +70615,7 @@ async function writeArchiveAtomically(outputPath, archive, overwrite) {
71624
70615
  await (0, import_promises13.mkdir)((0, import_node_path31.dirname)(outputPath), { recursive: true });
71625
70616
  const temporaryPath = (0, import_node_path31.join)(
71626
70617
  (0, import_node_path31.dirname)(outputPath),
71627
- `.${(0, import_node_path31.basename)(outputPath)}.${(0, import_node_crypto15.randomUUID)()}.tmp`
70618
+ `.${(0, import_node_path31.basename)(outputPath)}.${(0, import_node_crypto14.randomUUID)()}.tmp`
71628
70619
  );
71629
70620
  try {
71630
70621
  await (0, import_promises13.writeFile)(temporaryPath, archive, { flag: "wx", mode: 384 });
@@ -71643,7 +70634,7 @@ async function writeArchiveAtomically(outputPath, archive, overwrite) {
71643
70634
  }
71644
70635
  }
71645
70636
  function hashDiagnosticFileContent(content) {
71646
- return (0, import_node_crypto15.createHash)("sha256").update(content).digest("hex");
70637
+ return (0, import_node_crypto14.createHash)("sha256").update(content).digest("hex");
71647
70638
  }
71648
70639
  function isUnavailableError(err) {
71649
70640
  return !!err && typeof err === "object" && "diagnosticUnavailable" in err;
@@ -71903,7 +70894,7 @@ function isProvider2(value) {
71903
70894
  }
71904
70895
 
71905
70896
  // src/logs-export-utils.ts
71906
- var import_node_crypto16 = require("node:crypto");
70897
+ var import_node_crypto15 = require("node:crypto");
71907
70898
  var import_node_fs26 = require("node:fs");
71908
70899
  var import_promises14 = require("node:fs/promises");
71909
70900
  var import_node_path33 = require("node:path");
@@ -72046,7 +71037,7 @@ async function assertRegularFile2(path2) {
72046
71037
  }
72047
71038
  async function inspectRegularFile(path2) {
72048
71039
  const file = await assertRegularFile2(path2);
72049
- const hash2 = (0, import_node_crypto16.createHash)("sha256");
71040
+ const hash2 = (0, import_node_crypto15.createHash)("sha256");
72050
71041
  for await (const chunk of (0, import_node_fs26.createReadStream)(path2)) {
72051
71042
  hash2.update(chunk);
72052
71043
  }
@@ -72299,7 +71290,7 @@ async function exportDiagnosticLogs(options) {
72299
71290
  node: process.version,
72300
71291
  platform: process.platform,
72301
71292
  arch: process.arch,
72302
- packageVersion: true ? "0.2.18-beta-4dd056b897-261015113839" : "unknown",
71293
+ packageVersion: true ? "0.2.18" : "unknown",
72303
71294
  sensitiveContentIncluded: options.includeSensitiveContent,
72304
71295
  listenerAndLlmContentIncluded: true,
72305
71296
  credentialsAlwaysRedacted: true,
@@ -74211,7 +73202,7 @@ async function runDoctor(options = {}) {
74211
73202
  platform: options.platform ?? process.platform,
74212
73203
  env: options.env ?? process.env,
74213
73204
  target: options.target ?? resolveDoctorTarget(options.env ?? process.env),
74214
- cliVersion: options.cliVersion ?? (true ? "0.2.18-beta-4dd056b897-261015113839" : "0.0.0"),
73205
+ cliVersion: options.cliVersion ?? (true ? "0.2.18" : "0.0.0"),
74215
73206
  fixMode: options.fix === true,
74216
73207
  nonInteractive: options.nonInteractive === true,
74217
73208
  packageChanged: false,
@@ -74458,7 +73449,6 @@ init_autostart_windows();
74458
73449
  InboundReplayGate,
74459
73450
  InvalidXmtpMessageStore,
74460
73451
  JOB_PROVIDER_BINDING_SOURCES,
74461
- LIST_JOBS_BY_VERIFIED_SENDER_HELP_TOKEN,
74462
73452
  ListenerDeferredTaskScheduler,
74463
73453
  ListenerMaintenanceGate,
74464
73454
  LogEvent,
@@ -74468,9 +73458,6 @@ init_autostart_windows();
74468
73458
  NATIVE_LAUNCHER_EXE_NAME,
74469
73459
  OPENCLAW_GATEWAY_ROUTE_GROUP_ID,
74470
73460
  ProviderNotReadyError,
74471
- RUN_LOG_FILENAME_MAX_BYTES,
74472
- SUBSCRIPTION_FANOUT_MAX,
74473
- SUBSCRIPTION_MESSAGE_TYPE,
74474
73461
  SYSTEM_NOTIFICATION_SESSION_KEY,
74475
73462
  SessionBusyTracker,
74476
73463
  SessionStore,
@@ -74516,9 +73503,7 @@ init_autostart_windows();
74516
73503
  buildInboundTerminalExtras,
74517
73504
  buildLaunchdPlist,
74518
73505
  buildLauncherEntryJs,
74519
- buildListJobsByVerifiedSenderArgs,
74520
73506
  buildMessageEligibleArgs,
74521
- buildRunLogFileName,
74522
73507
  buildSchtasksCreateArgs,
74523
73508
  buildSchtasksDeleteArgs,
74524
73509
  buildSchtasksEndArgs,
@@ -74527,14 +73512,9 @@ init_autostart_windows();
74527
73512
  buildSeaConfig,
74528
73513
  buildServicePath,
74529
73514
  buildSessionKey,
74530
- buildSubscriptionEnvelope,
74531
- buildSubscriptionInboundExtras,
74532
- buildSubscriptionJobExtras,
74533
- buildSubscriptionSendExtras,
74534
73515
  buildSystemMessageNotice,
74535
73516
  buildSystemStoredMessage,
74536
73517
  buildSystemdUserService,
74537
- buildUpgradeRecommendationNotice,
74538
73518
  buildWin32OnchainosCandidates,
74539
73519
  buildWindowsParentProcessProbe,
74540
73520
  buildXmtpMessageSentExtra,
@@ -74549,7 +73529,6 @@ init_autostart_windows();
74549
73529
  checkCodexReadiness,
74550
73530
  claimActiveDaemon,
74551
73531
  classifyJobBindingSource,
74552
- classifyListJobsError,
74553
73532
  clearCodexReadinessCache,
74554
73533
  codexCommandResolvesWithoutOverride,
74555
73534
  codexReadinessCacheKey,
@@ -74561,12 +73540,10 @@ init_autostart_windows();
74561
73540
  createOutboundBehavior,
74562
73541
  createUserAttentionWatchParentMonitor,
74563
73542
  currentOpenClawGatewaySessionKey,
74564
- decideSubscriptionGate,
74565
73543
  detectAiProviders,
74566
73544
  detectAiRuntimeSurface,
74567
73545
  detectCurrentAiProvider,
74568
73546
  detectGatewayInvocation,
74569
- detectListJobsByVerifiedSenderSupport,
74570
73547
  detectMessageEligibleOfflineReplaySupport,
74571
73548
  detectRuntime,
74572
73549
  ensureDaemonReady,
@@ -74580,7 +73557,6 @@ init_autostart_windows();
74580
73557
  extractDirectToUserNotification,
74581
73558
  extractRateLimitEndpoint,
74582
73559
  extractXmtpSentAtMs,
74583
- fanOutSubscriptionJobs,
74584
73560
  findWindowsNativeOkxA2aExe,
74585
73561
  followFile,
74586
73562
  formatDoctorReportForHumans,
@@ -74593,7 +73569,6 @@ init_autostart_windows();
74593
73569
  getXmtpCreationCooldown,
74594
73570
  handleCapabilitiesCommand,
74595
73571
  handleDoctorCommand,
74596
- handleSubscriptionPushCommand,
74597
73572
  handleXmtpDebugCommand,
74598
73573
  handleXmtpSendCommand,
74599
73574
  handleXmtpTestCommand,
@@ -74608,7 +73583,6 @@ init_autostart_windows();
74608
73583
  invalidateResolvedOnchainosBinForTests,
74609
73584
  isAutostartManagerUnavailableError,
74610
73585
  isDefaultTaskHome,
74611
- isFingerprintKey,
74612
73586
  isGatewayAvailableForHeartbeat,
74613
73587
  isHermesGatewayPluginEnabled,
74614
73588
  isInfoEventAllowlisted,
@@ -74619,7 +73593,6 @@ init_autostart_windows();
74619
73593
  isPrereleaseVersion,
74620
73594
  isRetryableOpenClawGatewayError,
74621
73595
  isSqliteBusyError,
74622
- isSubscriptionEnvelope,
74623
73596
  isSystemdManagerUnavailableMessage,
74624
73597
  isTagKey,
74625
73598
  isValidExternalJobId,
@@ -74628,12 +73601,8 @@ init_autostart_windows();
74628
73601
  killProcessTree,
74629
73602
  launchdPlistHasCurrentRestartPolicy,
74630
73603
  listAllAgentsWithMetadata,
74631
- listJobsByVerifiedSender,
74632
- listJobsByVerifiedSenderHelpAdvertisesCommand,
74633
- listJobsByVerifiedSenderWithCapability,
74634
73604
  logWinCompat,
74635
73605
  logXmtpMessageSent,
74636
- logger,
74637
73606
  maybeRecommendOnchainosUpgrade,
74638
73607
  mergeA2AEnvelopeTips,
74639
73608
  messageEligibleHelpAdvertisesOfflineReplay,
@@ -74641,8 +73610,6 @@ init_autostart_windows();
74641
73610
  normalizeAiProvider,
74642
73611
  normalizeAiRuntimeProvider,
74643
73612
  normalizeHermesOkxA2aPluginConfig,
74644
- normalizeListJobsResponse,
74645
- normalizeSubscriptionJobs,
74646
73613
  notifyAgentMessageToUserAttention,
74647
73614
  notifyDirectToUserAttention,
74648
73615
  notifySystemMessageToUser,
@@ -74653,7 +73620,6 @@ init_autostart_windows();
74653
73620
  parsePluginYamlVersion,
74654
73621
  parseWalletLoginStatus,
74655
73622
  parseWindowsParentProcessJson,
74656
- partitionSubscriptionJobsByOwner,
74657
73623
  performRuntimeSwitch,
74658
73624
  persistAiRuntimeSurfaceBestEffort,
74659
73625
  persistCurrentRuntimeSelectionForNewJob,
@@ -74663,14 +73629,12 @@ init_autostart_windows();
74663
73629
  printXmtpTestUsage,
74664
73630
  probeCodexAuthStatus,
74665
73631
  processFileMessage,
74666
- processSubscriptionInbound,
74667
73632
  queryWalletLoginStatus,
74668
73633
  readAiProviderTimeoutMs,
74669
73634
  readAiRuntimeSurfaceBestEffort,
74670
73635
  readCachedCodexReadiness,
74671
73636
  readLastLines,
74672
73637
  readParentProcessCommandForPlatform,
74673
- readSubscriptionEnvelope,
74674
73638
  readUserAttentionWatcherEvent,
74675
73639
  refreshAgentsAndWait,
74676
73640
  refreshOnchainosVersionMetadata,
@@ -74681,10 +73645,8 @@ init_autostart_windows();
74681
73645
  replayScanBackoffWithJitterMs,
74682
73646
  reportDoctorRunToSentry,
74683
73647
  reportUserNotificationFailure,
74684
- resetListJobsByVerifiedSenderCapabilityForTests,
74685
73648
  resetMessageEligibleOfflineReplayCapabilityForTests,
74686
73649
  resetResolvedOnchainosBinForTests,
74687
- resetSubscriptionTargetsForTests,
74688
73650
  resetXmtpCreationCooldownForTests,
74689
73651
  resolveAiPermissionPreset,
74690
73652
  resolveAiProviderCommand,
@@ -74738,8 +73700,6 @@ init_autostart_windows();
74738
73700
  stopOpenClawGateway,
74739
73701
  stopSystemdAutostart,
74740
73702
  subscribeUserAttentionEvents,
74741
- subscriptionIdempotencyKey,
74742
- summarizeSubscriptionPush,
74743
73703
  summarizeXmtpTestEvents,
74744
73704
  switchProvider,
74745
73705
  switchProviderWithReadinessGate,
@@ -74748,7 +73708,6 @@ init_autostart_windows();
74748
73708
  tailFile,
74749
73709
  toOpenClawGatewaySessionKey,
74750
73710
  toWindowsInvocation,
74751
- tryMarkSubscriptionTarget,
74752
73711
  writeAiPermissionPresetToConfig
74753
73712
  });
74754
73713
  /*! Bundled license information: