@okxweb3/a2a-node 0.2.4-beta-e7a52faf6f-260812154627 → 0.2.4

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 +267 -169
  2. package/dist/index.js +224 -168
  3. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -26604,7 +26604,7 @@ function buildConnectParams(config, instanceId, protocolVersion) {
26604
26604
  client: {
26605
26605
  id: "gateway-client",
26606
26606
  displayName: "okx-a2a-node",
26607
- version: "0.2.4-beta-e7a52faf6f-260812154627",
26607
+ version: "0.2.4",
26608
26608
  platform: "node",
26609
26609
  mode: "backend",
26610
26610
  instanceId
@@ -26615,7 +26615,7 @@ function buildConnectParams(config, instanceId, protocolVersion) {
26615
26615
  commands: [],
26616
26616
  permissions: {},
26617
26617
  locale: Intl.DateTimeFormat().resolvedOptions().locale || "en-US",
26618
- userAgent: `okx-a2a-node/${"0.2.4-beta-e7a52faf6f-260812154627"}`,
26618
+ userAgent: `okx-a2a-node/${"0.2.4"}`,
26619
26619
  auth: {
26620
26620
  ...config.token ? { token: config.token } : {},
26621
26621
  ...config.password ? { password: config.password } : {}
@@ -28181,6 +28181,31 @@ var init_runtime_switch = __esm({
28181
28181
  }
28182
28182
  });
28183
28183
 
28184
+ // src/job-provider.ts
28185
+ function setJobProvider(options) {
28186
+ return options.store.setJobProviderBinding({
28187
+ jobId: options.jobId,
28188
+ provider: normalizeAiProvider(options.provider)
28189
+ });
28190
+ }
28191
+ function setJobProviderToCurrentPlatform(options) {
28192
+ const provider = detectCurrentAiProvider(options.env ?? process.env);
28193
+ if (!provider) {
28194
+ return null;
28195
+ }
28196
+ return setJobProvider({
28197
+ store: options.store,
28198
+ jobId: options.jobId,
28199
+ provider
28200
+ });
28201
+ }
28202
+ var init_job_provider = __esm({
28203
+ "src/job-provider.ts"() {
28204
+ "use strict";
28205
+ init_ai_provider();
28206
+ }
28207
+ });
28208
+
28184
28209
  // src/task-config.ts
28185
28210
  function resolveAiPermissionPreset(options = {}) {
28186
28211
  const env = options.env ?? process.env;
@@ -28499,7 +28524,7 @@ var init_sentry_config = __esm({
28499
28524
  environment = process.env.SENTRY_ENV === "dev" ? "dev" : "prod";
28500
28525
  SENTRY_CONFIG = {
28501
28526
  projectName: "okx/openclaw-okx-a2a-extension",
28502
- release: "0.2.4-beta-e7a52faf6f-260812154627",
28527
+ release: "0.2.4",
28503
28528
  environment,
28504
28529
  runtimeContainer: normalizeRuntimeContainer(process.env.OKX_A2A_RUNTIME_CONTAINER)
28505
28530
  };
@@ -39669,7 +39694,7 @@ async function exportDiagnosticLogs(options) {
39669
39694
  node: process.version,
39670
39695
  platform: process.platform,
39671
39696
  arch: process.arch,
39672
- packageVersion: true ? "0.2.4-beta-e7a52faf6f-260812154627" : "unknown",
39697
+ packageVersion: true ? "0.2.4" : "unknown",
39673
39698
  sensitiveContentIncluded: options.includeSensitiveContent,
39674
39699
  listenerAndLlmContentIncluded: true,
39675
39700
  credentialsAlwaysRedacted: true,
@@ -55597,14 +55622,24 @@ function extractStreamErrorTelemetry(error) {
55597
55622
  }
55598
55623
  return telemetry;
55599
55624
  }
55600
- function createKeyedFlight(discriminator, operation) {
55625
+ function replayFlightDiscriminator(clientGeneration, isOfflineReplay) {
55626
+ return isOfflineReplay ? `startup_offline:${clientGeneration}` : `online_repair:${clientGeneration}`;
55627
+ }
55628
+ function createKeyedFlight(discriminator, operation, shouldRunAfterActive) {
55601
55629
  let resolve14;
55602
55630
  let reject;
55603
55631
  const promise = new Promise((resolvePromise, rejectPromise) => {
55604
55632
  resolve14 = resolvePromise;
55605
55633
  reject = rejectPromise;
55606
55634
  });
55607
- return { discriminator, operation, promise, resolve: resolve14, reject };
55635
+ return {
55636
+ discriminator,
55637
+ operation,
55638
+ promise,
55639
+ resolve: resolve14,
55640
+ reject,
55641
+ shouldRunAfterActive
55642
+ };
55608
55643
  }
55609
55644
  var TRANSPORT_FAILURE_PATTERNS, KNOWN_CAUSE_CODES, KNOWN_CAUSE_KINDS, KNOWN_GRPC_METHODS, StreamRecoveryTelemetry, KeyedSingleFlight;
55610
55645
  var init_stream_recovery_telemetry = __esm({
@@ -55632,6 +55667,7 @@ var init_stream_recovery_telemetry = __esm({
55632
55667
  }
55633
55668
  markError(nowMs = Date.now()) {
55634
55669
  if (this.activeRecovery) {
55670
+ this.activeRecovery.candidateStartedAtMs = void 0;
55635
55671
  return {
55636
55672
  recoverySequence: this.activeRecovery.sequence,
55637
55673
  alreadyRecovering: true
@@ -55645,9 +55681,26 @@ var init_stream_recovery_telemetry = __esm({
55645
55681
  if (!this.activeRecovery) {
55646
55682
  return void 0;
55647
55683
  }
55684
+ this.activeRecovery.candidateStartedAtMs = nowMs;
55685
+ return {
55686
+ recoverySequence: this.activeRecovery.sequence,
55687
+ candidateStartedAtMs: nowMs
55688
+ };
55689
+ }
55690
+ markStable(nowMs = Date.now()) {
55691
+ if (this.activeRecovery?.candidateStartedAtMs === void 0) {
55692
+ return void 0;
55693
+ }
55648
55694
  const completed = {
55649
55695
  recoverySequence: this.activeRecovery.sequence,
55650
- recoveryDurationMs: Math.max(0, nowMs - this.activeRecovery.startedAtMs)
55696
+ recoveryDurationMs: Math.max(
55697
+ 0,
55698
+ this.activeRecovery.candidateStartedAtMs - this.activeRecovery.startedAtMs
55699
+ ),
55700
+ recoveryConfirmationDurationMs: Math.max(
55701
+ 0,
55702
+ nowMs - this.activeRecovery.startedAtMs
55703
+ )
55651
55704
  };
55652
55705
  this.activeRecovery = void 0;
55653
55706
  return completed;
@@ -55658,7 +55711,7 @@ var init_stream_recovery_telemetry = __esm({
55658
55711
  };
55659
55712
  KeyedSingleFlight = class {
55660
55713
  inFlight = /* @__PURE__ */ new Map();
55661
- run(key, discriminator, operation) {
55714
+ run(key, discriminator, operation, options = {}) {
55662
55715
  const normalizedKey = key.toLowerCase();
55663
55716
  const state = this.inFlight.get(normalizedKey);
55664
55717
  if (!state) {
@@ -55668,7 +55721,22 @@ var init_stream_recovery_telemetry = __esm({
55668
55721
  return active.promise;
55669
55722
  }
55670
55723
  if (state.active.discriminator === discriminator) {
55671
- return state.active.promise;
55724
+ if (!options.queueBehindActive) {
55725
+ return state.active.promise;
55726
+ }
55727
+ const queued2 = state.queued.find(
55728
+ (flight3) => flight3.discriminator === discriminator
55729
+ );
55730
+ if (queued2) {
55731
+ return queued2.promise;
55732
+ }
55733
+ const flight2 = createKeyedFlight(
55734
+ discriminator,
55735
+ operation,
55736
+ options.shouldRunAfterActive
55737
+ );
55738
+ state.queued.push(flight2);
55739
+ return flight2.promise;
55672
55740
  }
55673
55741
  const queued = state.queued.find(
55674
55742
  (flight2) => flight2.discriminator === discriminator
@@ -55684,15 +55752,15 @@ var init_stream_recovery_telemetry = __esm({
55684
55752
  void Promise.resolve().then(flight.operation).then(
55685
55753
  (value) => {
55686
55754
  flight.resolve(value);
55687
- this.advance(key, flight);
55755
+ this.advanceAfterSuccess(key, flight, value);
55688
55756
  },
55689
55757
  (error) => {
55690
55758
  flight.reject(error);
55691
- this.advance(key, flight);
55759
+ this.advanceAfterFailure(key, flight, error);
55692
55760
  }
55693
55761
  );
55694
55762
  }
55695
- advance(key, completed) {
55763
+ advanceAfterSuccess(key, completed, value) {
55696
55764
  const state = this.inFlight.get(key);
55697
55765
  if (state?.active !== completed) {
55698
55766
  return;
@@ -55702,6 +55770,29 @@ var init_stream_recovery_telemetry = __esm({
55702
55770
  this.inFlight.delete(key);
55703
55771
  return;
55704
55772
  }
55773
+ if (next.shouldRunAfterActive && !next.shouldRunAfterActive(value)) {
55774
+ next.resolve(value);
55775
+ this.advanceAfterSuccess(key, completed, value);
55776
+ return;
55777
+ }
55778
+ state.active = next;
55779
+ this.execute(key, next);
55780
+ }
55781
+ advanceAfterFailure(key, completed, error) {
55782
+ const state = this.inFlight.get(key);
55783
+ if (state?.active !== completed) {
55784
+ return;
55785
+ }
55786
+ const next = state.queued.shift();
55787
+ if (!next) {
55788
+ this.inFlight.delete(key);
55789
+ return;
55790
+ }
55791
+ if (next.shouldRunAfterActive) {
55792
+ next.reject(error);
55793
+ this.advanceAfterFailure(key, completed, error);
55794
+ return;
55795
+ }
55705
55796
  state.active = next;
55706
55797
  this.execute(key, next);
55707
55798
  }
@@ -56567,11 +56658,11 @@ function replayScanBackoffMs(consecutiveFailures) {
56567
56658
  function isOfflineReplayForTrigger(trigger) {
56568
56659
  return trigger === "startup";
56569
56660
  }
56570
- function replaySingleFlightDiscriminator(trigger, clientGeneration, recoveryIdentity) {
56571
- if (trigger === "stream_recovery") {
56572
- return `stream_recovery:${clientGeneration}:${recoveryIdentity ?? "unknown"}`;
56573
- }
56574
- return isOfflineReplayForTrigger(trigger) ? `startup_offline:${clientGeneration}` : `online_repair:${clientGeneration}`;
56661
+ function replaySingleFlightDiscriminator(trigger, clientGeneration) {
56662
+ return replayFlightDiscriminator(
56663
+ clientGeneration,
56664
+ isOfflineReplayForTrigger(trigger)
56665
+ );
56575
56666
  }
56576
56667
  function createOfflineReplayAddressSummary(address) {
56577
56668
  return {
@@ -56591,7 +56682,7 @@ function createOfflineReplayAddressSummary(address) {
56591
56682
  durationMs: 0
56592
56683
  };
56593
56684
  }
56594
- var import_node_fs22, import_node_path26, DEFAULT_DATA_DIR, XMTP_INSTALLATION_WARNING_THRESHOLD, XMTP_INSTALLATION_NEAR_LIMIT_THRESHOLD, REPLAY_SCAN_INITIAL_BACKOFF_MS, REPLAY_SCAN_MAX_BACKOFF_MS, SENSITIVE_WORDS_LAZY_RETRY_COOLDOWN_MS, InboundReplayGate, SYSTEM_CONFIG_DEFAULTS, STREAM_RECOVERY_ALERT_THRESHOLD_MS, REPLAY_GATE_DRAIN_MAX_ATTEMPTS, REPLAY_GATE_DRAIN_RETRY_DELAY_MS, SEMVER_RE, isRecord5, isPositiveNumber, SYSTEM_CONFIG_VALIDATORS, XmtpService;
56685
+ var import_node_fs22, import_node_path26, DEFAULT_DATA_DIR, XMTP_INSTALLATION_WARNING_THRESHOLD, XMTP_INSTALLATION_NEAR_LIMIT_THRESHOLD, REPLAY_SCAN_INITIAL_BACKOFF_MS, REPLAY_SCAN_MAX_BACKOFF_MS, SENSITIVE_WORDS_LAZY_RETRY_COOLDOWN_MS, InboundReplayGate, SYSTEM_CONFIG_DEFAULTS, STREAM_RECOVERY_ALERT_THRESHOLD_MS, STREAM_RECOVERY_STABILITY_WINDOW_MS, REPLAY_GATE_DRAIN_MAX_ATTEMPTS, REPLAY_GATE_DRAIN_RETRY_DELAY_MS, SEMVER_RE, isRecord5, isPositiveNumber, SYSTEM_CONFIG_VALIDATORS, XmtpService;
56595
56686
  var init_xmtp_sdk = __esm({
56596
56687
  "../core/src/xmtp-sdk/index.ts"() {
56597
56688
  "use strict";
@@ -56699,6 +56790,7 @@ var init_xmtp_sdk = __esm({
56699
56790
  }
56700
56791
  };
56701
56792
  STREAM_RECOVERY_ALERT_THRESHOLD_MS = 3e4;
56793
+ STREAM_RECOVERY_STABILITY_WINDOW_MS = 1e4;
56702
56794
  REPLAY_GATE_DRAIN_MAX_ATTEMPTS = 3;
56703
56795
  REPLAY_GATE_DRAIN_RETRY_DELAY_MS = 100;
56704
56796
  SEMVER_RE = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*)?$/;
@@ -56753,6 +56845,9 @@ var init_xmtp_sdk = __esm({
56753
56845
  replayScanClearTimeout = (timer) => clearTimeout(timer);
56754
56846
  inboundReplayGates = /* @__PURE__ */ new Map();
56755
56847
  streamRecoveryCleanupByAddress = /* @__PURE__ */ new Map();
56848
+ streamRecoverySetTimeout = (callback, delayMs) => setTimeout(callback, delayMs);
56849
+ streamRecoveryClearTimeout = (timer) => clearTimeout(timer);
56850
+ streamStartSetTimeout = (callback, delayMs) => setTimeout(callback, delayMs);
56756
56851
  nextClientGeneration = 1;
56757
56852
  clientGenerationByClient = /* @__PURE__ */ new WeakMap();
56758
56853
  resolveStartupReplayCompletion;
@@ -58205,10 +58300,14 @@ var init_xmtp_sdk = __esm({
58205
58300
  }
58206
58301
  const delay = BASE_DELAY_MS * 2 ** attempt;
58207
58302
  logWithTimestamp(`${tag} reconnecting in ${delay}ms (attempt=${attempt + 1})`);
58208
- setTimeout(() => void startWithRetry(attempt + 1), delay);
58303
+ this.streamStartSetTimeout(
58304
+ () => void startWithRetry(attempt + 1),
58305
+ delay
58306
+ );
58209
58307
  };
58210
58308
  const streamRecovery = new StreamRecoveryTelemetry();
58211
58309
  let recoveryTimeout;
58310
+ let recoveryStabilityTimeout;
58212
58311
  let pendingRecoveryGate;
58213
58312
  let recoveryDisposed = false;
58214
58313
  this.cancelStreamRecoveryForAddress(address);
@@ -58216,9 +58315,13 @@ var init_xmtp_sdk = __esm({
58216
58315
  recoveryDisposed = true;
58217
58316
  streamRecovery.cancel();
58218
58317
  if (recoveryTimeout) {
58219
- clearTimeout(recoveryTimeout);
58318
+ this.streamRecoveryClearTimeout(recoveryTimeout);
58220
58319
  recoveryTimeout = void 0;
58221
58320
  }
58321
+ if (recoveryStabilityTimeout) {
58322
+ this.streamRecoveryClearTimeout(recoveryStabilityTimeout);
58323
+ recoveryStabilityTimeout = void 0;
58324
+ }
58222
58325
  };
58223
58326
  this.streamRecoveryCleanupByAddress.set(
58224
58327
  addressKey,
@@ -58233,6 +58336,10 @@ var init_xmtp_sdk = __esm({
58233
58336
  logger.error(LogEvent.AGENT_UNHANDLED_ERROR, err2, agentExtras(identity));
58234
58337
  return;
58235
58338
  }
58339
+ if (recoveryStabilityTimeout) {
58340
+ this.streamRecoveryClearTimeout(recoveryStabilityTimeout);
58341
+ recoveryStabilityTimeout = void 0;
58342
+ }
58236
58343
  const recovery = streamRecovery.markError();
58237
58344
  const errorTelemetry = extractStreamErrorTelemetry(err2);
58238
58345
  if (!recovery.alreadyRecovering) {
@@ -58247,10 +58354,11 @@ var init_xmtp_sdk = __esm({
58247
58354
  recoveryAlreadyActive: String(recovery.alreadyRecovering)
58248
58355
  });
58249
58356
  if (!recovery.alreadyRecovering) {
58250
- recoveryTimeout = setTimeout(() => {
58357
+ recoveryTimeout = this.streamRecoverySetTimeout(() => {
58251
58358
  if (recoveryDisposed || this.clients.get(address) !== agent || this.stoppedAddresses.has(addressKey) || streamRecovery.activeSequence !== recovery.recoverySequence) {
58252
58359
  return;
58253
58360
  }
58361
+ recoveryTimeout = void 0;
58254
58362
  logger.error(LogEvent.AGENT_STREAM_RECOVERY_TIMEOUT, void 0, {
58255
58363
  ...agentExtras(identity),
58256
58364
  ...errorTelemetry,
@@ -58259,6 +58367,22 @@ var init_xmtp_sdk = __esm({
58259
58367
  recoveryDurationMs: String(STREAM_RECOVERY_ALERT_THRESHOLD_MS),
58260
58368
  thresholdMs: String(STREAM_RECOVERY_ALERT_THRESHOLD_MS)
58261
58369
  });
58370
+ const timedOutGate = pendingRecoveryGate;
58371
+ pendingRecoveryGate = void 0;
58372
+ void this.drainInboundReplayGate(address, timedOutGate).catch(
58373
+ (drainError) => {
58374
+ logger.error(
58375
+ LogEvent.OFFLINE_REPLAY_FAILED,
58376
+ drainError instanceof Error ? drainError : new Error(String(drainError)),
58377
+ {
58378
+ ...agentExtras(identity),
58379
+ clientGeneration: String(clientGeneration),
58380
+ recoverySequence: String(recovery.recoverySequence),
58381
+ stage: "streamRecovery/timeout-drain-gate"
58382
+ }
58383
+ );
58384
+ }
58385
+ );
58262
58386
  }, STREAM_RECOVERY_ALERT_THRESHOLD_MS);
58263
58387
  }
58264
58388
  });
@@ -58266,60 +58390,61 @@ var init_xmtp_sdk = __esm({
58266
58390
  if (recoveryDisposed || this.clients.get(address) !== agent || this.stoppedAddresses.has(addressKey)) {
58267
58391
  return;
58268
58392
  }
58269
- const recovery = streamRecovery.markStarted();
58270
- if (recoveryTimeout) {
58271
- clearTimeout(recoveryTimeout);
58272
- recoveryTimeout = void 0;
58273
- }
58393
+ const candidate = streamRecovery.markStarted();
58274
58394
  logWithTimestamp(
58275
58395
  `${tag} agent stream started agentId=${identity.onchainosAgentId ?? "(unknown)"} inboxId=${identity.inboxId ?? "(unknown)"} role=${identity.role ?? "(unknown)"} consentStates=Allowed,Unknown lastSync=${formatLogTimestamp2(this.syncByAddress.get(address))}`
58276
58396
  );
58277
- if (recovery) {
58278
- const recoveryGate = pendingRecoveryGate;
58279
- pendingRecoveryGate = void 0;
58280
- logger.info(LogEvent.AGENT_STREAM_RECOVERED, {
58281
- ...agentExtras(identity),
58282
- clientGeneration: String(clientGeneration),
58283
- recoverySequence: String(recovery.recoverySequence),
58284
- recoveryDurationMs: String(recovery.recoveryDurationMs)
58285
- });
58286
- void (async () => {
58287
- try {
58288
- const summary = await this.replayOfflineMessagesForStreamRecovery(
58289
- address,
58290
- String(recovery.recoverySequence),
58291
- agent
58292
- );
58293
- if (summary.outcome === "completed" && !recoveryDisposed && this.clients.get(address) === agent) {
58294
- logger.info(LogEvent.AGENT_STREAM_RECOVERY_REPLAY_COMPLETED, {
58295
- ...agentExtras(identity),
58296
- clientGeneration: String(clientGeneration),
58297
- recoverySequence: String(recovery.recoverySequence),
58298
- replayed: String(summary.replayed),
58299
- skipped: String(summary.skipped),
58300
- conversationCount: String(summary.conversations),
58301
- replayDurationMs: String(summary.durationMs),
58302
- outcome: "success",
58303
- replayOutcome: summary.outcome
58304
- });
58305
- }
58306
- } catch (err2) {
58307
- logWithTimestamp(`${tag} recovery offline replay failed:`, err2);
58308
- logger.error(
58309
- LogEvent.OFFLINE_REPLAY_FAILED,
58310
- err2 instanceof Error ? err2 : new Error(String(err2)),
58311
- {
58312
- ...agentExtras(identity),
58313
- clientGeneration: String(clientGeneration),
58314
- recoverySequence: String(recovery.recoverySequence),
58315
- stage: "streamRecovery/replay"
58316
- }
58317
- );
58318
- } finally {
58397
+ if (candidate) {
58398
+ if (recoveryStabilityTimeout) {
58399
+ this.streamRecoveryClearTimeout(recoveryStabilityTimeout);
58400
+ }
58401
+ recoveryStabilityTimeout = this.streamRecoverySetTimeout(() => {
58402
+ recoveryStabilityTimeout = void 0;
58403
+ if (recoveryDisposed || this.clients.get(address) !== agent || this.stoppedAddresses.has(addressKey) || streamRecovery.activeSequence !== candidate.recoverySequence) {
58404
+ return;
58405
+ }
58406
+ const recovery = streamRecovery.markStable();
58407
+ if (!recovery) {
58408
+ return;
58409
+ }
58410
+ if (recoveryTimeout) {
58411
+ this.streamRecoveryClearTimeout(recoveryTimeout);
58412
+ recoveryTimeout = void 0;
58413
+ }
58414
+ const recoveryGate = pendingRecoveryGate;
58415
+ pendingRecoveryGate = void 0;
58416
+ logger.info(LogEvent.AGENT_STREAM_RECOVERED, {
58417
+ ...agentExtras(identity),
58418
+ clientGeneration: String(clientGeneration),
58419
+ recoverySequence: String(recovery.recoverySequence),
58420
+ recoveryDurationMs: String(recovery.recoveryDurationMs),
58421
+ recoveryConfirmationDurationMs: String(
58422
+ recovery.recoveryConfirmationDurationMs
58423
+ ),
58424
+ stabilityWindowMs: String(STREAM_RECOVERY_STABILITY_WINDOW_MS)
58425
+ });
58426
+ void (async () => {
58319
58427
  try {
58320
- await this.drainInboundReplayGate(address, recoveryGate);
58428
+ const summary = await this.replayOfflineMessagesForStreamRecovery(
58429
+ address,
58430
+ String(recovery.recoverySequence),
58431
+ agent
58432
+ );
58433
+ if (summary.outcome === "completed" && !recoveryDisposed && this.clients.get(address) === agent) {
58434
+ logger.info(LogEvent.AGENT_STREAM_RECOVERY_REPLAY_COMPLETED, {
58435
+ ...agentExtras(identity),
58436
+ clientGeneration: String(clientGeneration),
58437
+ recoverySequence: String(recovery.recoverySequence),
58438
+ replayed: String(summary.replayed),
58439
+ skipped: String(summary.skipped),
58440
+ conversationCount: String(summary.conversations),
58441
+ replayDurationMs: String(summary.durationMs),
58442
+ outcome: "success",
58443
+ replayOutcome: summary.outcome
58444
+ });
58445
+ }
58321
58446
  } catch (err2) {
58322
- logWithTimestamp(`${tag} recovery replay gate drain failed:`, err2);
58447
+ logWithTimestamp(`${tag} recovery offline replay failed:`, err2);
58323
58448
  logger.error(
58324
58449
  LogEvent.OFFLINE_REPLAY_FAILED,
58325
58450
  err2 instanceof Error ? err2 : new Error(String(err2)),
@@ -58327,12 +58452,28 @@ var init_xmtp_sdk = __esm({
58327
58452
  ...agentExtras(identity),
58328
58453
  clientGeneration: String(clientGeneration),
58329
58454
  recoverySequence: String(recovery.recoverySequence),
58330
- stage: "streamRecovery/drain-gate"
58455
+ stage: "streamRecovery/replay"
58331
58456
  }
58332
58457
  );
58458
+ } finally {
58459
+ try {
58460
+ await this.drainInboundReplayGate(address, recoveryGate);
58461
+ } catch (err2) {
58462
+ logWithTimestamp(`${tag} recovery replay gate drain failed:`, err2);
58463
+ logger.error(
58464
+ LogEvent.OFFLINE_REPLAY_FAILED,
58465
+ err2 instanceof Error ? err2 : new Error(String(err2)),
58466
+ {
58467
+ ...agentExtras(identity),
58468
+ clientGeneration: String(clientGeneration),
58469
+ recoverySequence: String(recovery.recoverySequence),
58470
+ stage: "streamRecovery/drain-gate"
58471
+ }
58472
+ );
58473
+ }
58333
58474
  }
58334
- }
58335
- })();
58475
+ })();
58476
+ }, STREAM_RECOVERY_STABILITY_WINDOW_MS);
58336
58477
  }
58337
58478
  if (process.env.XMTP_FORCE_DEBUG === "true") {
58338
58479
  void logDetails(agent).catch((err2) => {
@@ -58351,7 +58492,7 @@ var init_xmtp_sdk = __esm({
58351
58492
  logWithTimestamp(`${tag} message listener started`);
58352
58493
  });
58353
58494
  }
58354
- async replayOfflineMessagesForAddress(address, expectedClient, trigger = "periodic_repair") {
58495
+ async replayOfflineMessagesForAddress(address, expectedClient, trigger = "periodic_repair", recoveryIdentity) {
58355
58496
  const addressReplayStartedAt = Date.now();
58356
58497
  const summary = createOfflineReplayAddressSummary(address);
58357
58498
  const isOfflineReplay = isOfflineReplayForTrigger(trigger);
@@ -58451,6 +58592,8 @@ var init_xmtp_sdk = __esm({
58451
58592
  walletAddress: address,
58452
58593
  stage: `offlineReplay/${stage}`,
58453
58594
  trigger,
58595
+ clientGeneration: String(clientGeneration),
58596
+ ...recoveryIdentity ? { recoverySequence: recoveryIdentity } : {},
58454
58597
  outcome: "failed",
58455
58598
  replayOutcome: summary.outcome,
58456
58599
  consecutiveFailures: String(consecutiveFailures),
@@ -58645,8 +58788,7 @@ var init_xmtp_sdk = __esm({
58645
58788
  const clientGeneration = expectedClient ? this.getClientGeneration(expectedClient) : "missing";
58646
58789
  const eligibilityClass = replaySingleFlightDiscriminator(
58647
58790
  trigger,
58648
- clientGeneration,
58649
- recoveryIdentity
58791
+ clientGeneration
58650
58792
  );
58651
58793
  return this.offlineReplaySingleFlight.run(
58652
58794
  address,
@@ -58656,9 +58798,14 @@ var init_xmtp_sdk = __esm({
58656
58798
  return this.replayOfflineMessagesForAddress(
58657
58799
  address,
58658
58800
  expectedClient,
58659
- trigger
58801
+ trigger,
58802
+ recoveryIdentity
58660
58803
  );
58661
- }
58804
+ },
58805
+ trigger === "stream_recovery" ? {
58806
+ queueBehindActive: true,
58807
+ shouldRunAfterActive: (summary) => summary.outcome === "completed"
58808
+ } : void 0
58662
58809
  );
58663
58810
  }
58664
58811
  async replayOfflineMessagesForStreamRecovery(address, recoveryIdentity, expectedClient) {
@@ -59609,14 +59756,9 @@ var init_signer = __esm({
59609
59756
  });
59610
59757
 
59611
59758
  // ../core/src/a2a/pending-conversation.ts
59612
- function buildPendingConversationBackupNotice(jobId) {
59613
- return PENDING_CONVERSATION_BACKUP_NOTICE_TEMPLATE.replace("${jobId}", jobId);
59614
- }
59615
- var PENDING_CONVERSATION_BACKUP_NOTICE_TEMPLATE;
59616
59759
  var init_pending_conversation = __esm({
59617
59760
  "../core/src/a2a/pending-conversation.ts"() {
59618
59761
  "use strict";
59619
- PENDING_CONVERSATION_BACKUP_NOTICE_TEMPLATE = "[event:provider_conversation][jobId:${jobId}] There are new conversation requests pending.";
59620
59762
  }
59621
59763
  });
59622
59764
 
@@ -65718,17 +65860,22 @@ async function maybeAllowProviderGroup(deps, chatType, conversationId) {
65718
65860
  );
65719
65861
  }
65720
65862
  }
65721
- function shouldKeepInboundGroupPendingForBuyer(input) {
65722
- return input.consentState === import_node_bindings2.ConsentState.Unknown && !input.hasExistingSession && (input.localAgentRole === 1 /* CLIENT */ || input.localAgentRole == null);
65723
- }
65724
- function buildPendingConversationBackupDispatch(input) {
65725
- return {
65726
- sessionKey: buildBackupJobSessionKey(input.jobId),
65727
- content: buildPendingConversationBackupNotice(input.jobId),
65728
- messageId: `pending-conversation:${input.messageId}`,
65863
+ function ensureInboundGroupSession(deps, input) {
65864
+ const sessionKey = buildSessionKey({
65729
65865
  jobId: input.jobId,
65730
- agentId: null
65731
- };
65866
+ myAgentId: input.myAgentId,
65867
+ toAgentId: input.toAgentId
65868
+ });
65869
+ deps.sessionStore?.upsertSession({
65870
+ sessionKey,
65871
+ jobId: input.jobId,
65872
+ myAgentId: input.myAgentId,
65873
+ toAgentId: input.toAgentId,
65874
+ groupId: input.groupId,
65875
+ myAgentXmtpAddress: deps.myXmtpAddress,
65876
+ toAgentXmtpAddress: input.toAgentXmtpAddress
65877
+ });
65878
+ return sessionKey;
65732
65879
  }
65733
65880
  function inboundStageExtras(stage, outcome) {
65734
65881
  return {
@@ -65785,30 +65932,6 @@ function buildInboundTerminalExtras(input) {
65785
65932
  })
65786
65933
  };
65787
65934
  }
65788
- function notifyPendingConversationToBackup(params) {
65789
- const event = buildPendingConversationBackupDispatch({
65790
- jobId: params.jobId,
65791
- messageId: params.messageId
65792
- });
65793
- void Promise.resolve(params.deps.onSessionMessage?.(event)).catch((err2) => {
65794
- logWithTimestamp(`[okx-agent-task:${params.deps.myXmtpAddress}] pending conversation backup dispatch failed:`, err2);
65795
- logger.error(LogEvent.INBOUND_DISPATCH_FAILED, toLoggableError(err2), {
65796
- ...buildInboundTerminalExtras({
65797
- terminalState: "dispatch_failed",
65798
- myXmtpAddress: params.deps.myXmtpAddress,
65799
- messageId: event.messageId,
65800
- jobId: params.jobId,
65801
- sessionKey: event.sessionKey,
65802
- route: "backup",
65803
- reason: "pending_backup_dispatch_failed"
65804
- }),
65805
- // Each fire-and-forget dispatch overrides the generic checkpoint with the
65806
- // `_failed` twin of its own success checkpoint, so the four paths stay
65807
- // distinguishable in the funnel.
65808
- checkpoint: "inbound/pending_backup_dispatch_failed"
65809
- });
65810
- });
65811
- }
65812
65935
  function maybeNotifyInboundAgentMessage(params) {
65813
65936
  if (params.chatType === "dm") {
65814
65937
  return;
@@ -66616,7 +66739,7 @@ async function processFileMessage(ctx, deps, options = {}) {
66616
66739
  }
66617
66740
  const sender = isPlainObject3(payloadObject?.sender) ? payloadObject.sender : null;
66618
66741
  const localAgent = service.getAgentByAddress(deps.myXmtpAddress);
66619
- const myAgentId = localAgent?.agentId ?? sessionAgentId ?? null;
66742
+ const myAgentId = localAgent?.agentId ?? readString5(payloadObject?.receiverAgentId) ?? sessionAgentId ?? null;
66620
66743
  const toAgentId = readString5(sender?.agentId);
66621
66744
  const accepted = await verifyInboundA2AGroupMessage({
66622
66745
  payload: parsed.parsed ? parsed.payload : null,
@@ -66634,50 +66757,13 @@ async function processFileMessage(ctx, deps, options = {}) {
66634
66757
  if (!accepted) {
66635
66758
  return true;
66636
66759
  }
66637
- const sessionKey = buildSessionKey({
66638
- jobId: route.jobId,
66639
- myAgentId,
66640
- toAgentId
66641
- });
66642
- const existingSession = deps.sessionStore?.getSession(sessionKey) ?? null;
66643
66760
  const routedMessageId = messageId || `group-${(0, import_node_crypto14.randomUUID)()}`;
66644
- const consentState = ctx.conversation instanceof Group ? ctx.conversation.consentState() : void 0;
66645
- if (shouldKeepInboundGroupPendingForBuyer({
66646
- consentState,
66647
- localAgentRole: localAgent?.role ?? null,
66648
- hasExistingSession: !!existingSession
66649
- })) {
66650
- logWithTimestamp(
66651
- `[okx-agent-task:${deps.myXmtpAddress}] buyer inbound group kept pending: session=${sessionKey} job=${shortenLogValue(route.jobId)} group=${conversationId} consent=${String(consentState)} message=${shortenLogValue(routedMessageId)}`
66652
- );
66653
- logger.info(LogEvent.INBOUND_BUYER_PENDING, {
66654
- ...agentExtras({ walletAddress: deps.myXmtpAddress, onchainosAgentId: localAgent?.agentId }),
66655
- peerWalletAddress: senderAddress,
66656
- peerInboxId: ctx.message.senderInboxId ?? "",
66657
- peerAgentId: toAgentId ?? "",
66658
- taskId: route.jobId,
66659
- conversationId,
66660
- messageId: routedMessageId,
66661
- consentState: String(consentState),
66662
- ...inboundStageExtras("inbound/buyer_pending", "pending"),
66663
- reason: "unknown_group_without_session",
66664
- ...timing.extras()
66665
- });
66666
- notifyPendingConversationToBackup({
66667
- deps,
66668
- jobId: route.jobId,
66669
- messageId: routedMessageId
66670
- });
66671
- return true;
66672
- }
66673
- deps.sessionStore?.upsertSession({
66674
- sessionKey,
66761
+ const sessionKey = ensureInboundGroupSession(deps, {
66675
66762
  jobId: route.jobId,
66676
66763
  myAgentId,
66677
66764
  toAgentId,
66678
- groupId: conversationId || null,
66679
- myAgentXmtpAddress: deps.myXmtpAddress,
66680
- toAgentXmtpAddress: senderAddress || null
66765
+ groupId: conversationId,
66766
+ toAgentXmtpAddress: senderAddress || readString5(payloadObject?.fromXmtpAddress)
66681
66767
  });
66682
66768
  const dispatchStartedAt = Date.now();
66683
66769
  void Promise.resolve(deps.onSessionMessage?.({
@@ -67397,12 +67483,12 @@ async function runListenerWithLock(options, paths) {
67397
67483
  });
67398
67484
  }
67399
67485
  });
67400
- service.setPluginVersion("0.2.4-beta-e7a52faf6f-260812154627");
67486
+ service.setPluginVersion("0.2.4");
67401
67487
  await service.init();
67402
67488
  const pluginVersionStatus = service.pluginVersionStatus;
67403
67489
  if (pluginVersionStatus.unavailable) {
67404
67490
  throw new Error(
67405
- `@okxweb3/a2a-node v${"0.2.4-beta-e7a52faf6f-260812154627"} is below the required minimum v${pluginVersionStatus.minVersion}`
67491
+ `@okxweb3/a2a-node v${"0.2.4"} is below the required minimum v${pluginVersionStatus.minVersion}`
67406
67492
  );
67407
67493
  }
67408
67494
  const systemConfig = service.getSystemConfig();
@@ -67420,7 +67506,7 @@ async function runListenerWithLock(options, paths) {
67420
67506
  onchainosAgentId: "*",
67421
67507
  reason: "system-config missing sentryDsn",
67422
67508
  pluginId: "@okxweb3/a2a-node",
67423
- pluginVersion: "0.2.4-beta-e7a52faf6f-260812154627"
67509
+ pluginVersion: "0.2.4"
67424
67510
  });
67425
67511
  }
67426
67512
  logWithTimestamp(
@@ -112604,6 +112690,13 @@ async function watchUserAttention(store, parsed, json) {
112604
112690
  throw new Error("--from-now has been removed; user watch always returns existing pending items first");
112605
112691
  }
112606
112692
  const jobId = normalizeWatchJobId(parsed.options.get("job-id"));
112693
+ if (jobId) {
112694
+ setJobProviderToCurrentPlatform({
112695
+ store,
112696
+ jobId,
112697
+ env: process.env
112698
+ });
112699
+ }
112607
112700
  const provider = readProviderFilter(store, parsed, jobId);
112608
112701
  const preparation = await prepareRuntimeSelectionForWatchedJob(store, jobId, json);
112609
112702
  assertWatchedJobPrepared(jobId, preparation, json);
@@ -113451,6 +113544,7 @@ var init_user_attention_cli = __esm({
113451
113544
  init_session_store();
113452
113545
  init_user_attention_ipc();
113453
113546
  init_ai_provider();
113547
+ init_job_provider();
113454
113548
  init_outbound_behavior();
113455
113549
  init_openclaw_gateway();
113456
113550
  init_openclaw_gateway_config();
@@ -115814,7 +115908,7 @@ async function getCurrentNodeCliVersion() {
115814
115908
  return await getGlobalNpmPackageVersion(UPDATE_PACKAGES.node) ?? getBundledNodeCliVersion();
115815
115909
  }
115816
115910
  function getBundledNodeCliVersion() {
115817
- return true ? "0.2.4-beta-e7a52faf6f-260812154627" : null;
115911
+ return true ? "0.2.4" : null;
115818
115912
  }
115819
115913
  function readConfiguredAiProvider() {
115820
115914
  const explicit = process.env.OKX_A2A_AI_PROVIDER || process.env.OKX_AGENT_TASK_AI_CLI;
@@ -116024,7 +116118,7 @@ async function updateHermes(release, options) {
116024
116118
  }
116025
116119
  }
116026
116120
  async function installGatewayPluginForDoctor(target) {
116027
- const release = isPrereleaseVersion("0.2.4-beta-e7a52faf6f-260812154627") ? "beta" : "latest";
116121
+ const release = isPrereleaseVersion("0.2.4") ? "beta" : "latest";
116028
116122
  const insideTargetGateway = detectGatewayInvocation() === target;
116029
116123
  const options = {
116030
116124
  restart: !insideTargetGateway,
@@ -117067,7 +117161,7 @@ async function runDoctor(options = {}) {
117067
117161
  platform: options.platform ?? process.platform,
117068
117162
  env: options.env ?? process.env,
117069
117163
  target: options.target ?? resolveDoctorTarget(options.env ?? process.env),
117070
- cliVersion: options.cliVersion ?? (true ? "0.2.4-beta-e7a52faf6f-260812154627" : "0.0.0"),
117164
+ cliVersion: options.cliVersion ?? (true ? "0.2.4" : "0.0.0"),
117071
117165
  fixMode: options.fix === true,
117072
117166
  nonInteractive: options.nonInteractive === true,
117073
117167
  packageChanged: false,
@@ -118055,6 +118149,7 @@ init_command_store();
118055
118149
  init_file_store();
118056
118150
  init_ai_provider();
118057
118151
  init_runtime_switch();
118152
+ init_job_provider();
118058
118153
  init_session_store();
118059
118154
  init_paths();
118060
118155
  init_task_config();
@@ -118064,7 +118159,7 @@ init_sentry_logger();
118064
118159
  init_sentry_config();
118065
118160
  var CURRENT_GATEWAY_SESSION_KEYS_ENV4 = "OKX_A2A_CURRENT_GATEWAY_SESSION_KEYS";
118066
118161
  function printUsage3() {
118067
- console.log(`okx-a2a ${"0.2.4-beta-e7a52faf6f-260812154627"}
118162
+ console.log(`okx-a2a ${"0.2.4"}
118068
118163
 
118069
118164
  Usage:
118070
118165
  okx-a2a <command> [options]
@@ -118104,7 +118199,7 @@ Run \`okx-a2a <command> -h\` for command-specific help.
118104
118199
  `);
118105
118200
  }
118106
118201
  function printVersion() {
118107
- console.log("0.2.4-beta-e7a52faf6f-260812154627");
118202
+ console.log("0.2.4");
118108
118203
  }
118109
118204
  function printDaemonUsage() {
118110
118205
  console.log(`Usage: okx-a2a daemon <start|restart|stop|status|autostart> [options]
@@ -119243,8 +119338,11 @@ async function handleJobProvider(args) {
119243
119338
  }
119244
119339
  if (subcommand === "set") {
119245
119340
  const jobId = readRequiredOption4(rest, "--job-id");
119246
- const provider = normalizeAiProvider(readRequiredOption4(rest, "--provider"));
119247
- const binding = store.setJobProviderBinding({ jobId, provider });
119341
+ const binding = setJobProvider({
119342
+ store,
119343
+ jobId,
119344
+ provider: readRequiredOption4(rest, "--provider")
119345
+ });
119248
119346
  if (json) {
119249
119347
  console.log(JSON.stringify({ ok: true, binding }));
119250
119348
  } else {
@@ -119540,7 +119638,7 @@ async function main() {
119540
119638
  if (command === "xmtp-test") {
119541
119639
  const { handleXmtpTestCommand: handleXmtpTestCommand2 } = await Promise.resolve().then(() => (init_xmtp_test_cli(), xmtp_test_cli_exports));
119542
119640
  await handleXmtpTestCommand2(process.argv.slice(3), {
119543
- packageVersion: "0.2.4-beta-e7a52faf6f-260812154627",
119641
+ packageVersion: "0.2.4",
119544
119642
  agentSdkVersion: "2.3.0",
119545
119643
  nodeSdkVersion: "6.1.0",
119546
119644
  nodeBindingsVersion: "1.11.0"