@okxweb3/a2a-node 0.2.9-beta-912b775358-260824171011 → 0.2.9

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 +214 -773
  2. package/dist/index.js +195 -738
  3. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -3992,34 +3992,6 @@ var init_command_store = __esm({
3992
3992
  }
3993
3993
  return null;
3994
3994
  }
3995
- /**
3996
- * Read-only lookup of a command's current lifecycle state by id. Returns null
3997
- * when no row exists. Used by the WakeupNotify recovery reconcile to decide
3998
- * whether an in-flight wakeup's command completed, failed, or was orphaned by a
3999
- * crash — it does not mutate the queue or alter recovery behavior.
4000
- */
4001
- getCommandState(commandId) {
4002
- const row = this.db.prepare(`
4003
- SELECT status, result_json, processing_started_at_ms FROM command_queue
4004
- WHERE id = ?
4005
- `).get(commandId);
4006
- if (!row?.status) {
4007
- return null;
4008
- }
4009
- let ok = null;
4010
- if (row.result_json) {
4011
- try {
4012
- ok = Boolean(JSON.parse(row.result_json).ok);
4013
- } catch {
4014
- ok = null;
4015
- }
4016
- }
4017
- return {
4018
- status: row.status,
4019
- ok,
4020
- processingStartedAtMs: row.processing_started_at_ms ?? null
4021
- };
4022
- }
4023
3995
  close() {
4024
3996
  this.db.close();
4025
3997
  }
@@ -4705,7 +4677,7 @@ var require_is = __commonJS({
4705
4677
  function isPrimitive(wat) {
4706
4678
  return wat === null || typeof wat !== "object" && typeof wat !== "function";
4707
4679
  }
4708
- function isPlainObject6(wat) {
4680
+ function isPlainObject4(wat) {
4709
4681
  return isBuiltin(wat, "Object");
4710
4682
  }
4711
4683
  function isEvent(wat) {
@@ -4721,7 +4693,7 @@ var require_is = __commonJS({
4721
4693
  return Boolean(wat && wat.then && typeof wat.then === "function");
4722
4694
  }
4723
4695
  function isSyntheticEvent(wat) {
4724
- return isPlainObject6(wat) && "nativeEvent" in wat && "preventDefault" in wat && "stopPropagation" in wat;
4696
+ return isPlainObject4(wat) && "nativeEvent" in wat && "preventDefault" in wat && "stopPropagation" in wat;
4725
4697
  }
4726
4698
  function isNaN2(wat) {
4727
4699
  return typeof wat === "number" && wat !== wat;
@@ -4744,7 +4716,7 @@ var require_is = __commonJS({
4744
4716
  exports2.isEvent = isEvent;
4745
4717
  exports2.isInstanceOf = isInstanceOf;
4746
4718
  exports2.isNaN = isNaN2;
4747
- exports2.isPlainObject = isPlainObject6;
4719
+ exports2.isPlainObject = isPlainObject4;
4748
4720
  exports2.isPrimitive = isPrimitive;
4749
4721
  exports2.isRegExp = isRegExp;
4750
4722
  exports2.isString = isString;
@@ -19959,6 +19931,7 @@ var init_events = __esm({
19959
19931
  AGENT_CLIENT_REMOVED: "Agent client removed",
19960
19932
  AGENT_STREAM_RECOVERED: "Agent stream recovered",
19961
19933
  AGENT_STREAM_RECOVERY_REPLAY_COMPLETED: "Agent stream recovery replay completed",
19934
+ AGENT_STREAM_RECOVERY_REPLAY_TERMINATED: "Agent stream recovery replay terminated",
19962
19935
  ADDRESS_SYNC_COMPLETED: "Address sync completed",
19963
19936
  AGENT_REFRESH_SESSION_EXPIRED: "Agent refresh aborted: onchainos session expired, local clients taken offline",
19964
19937
  OFFLINE_REPLAY_MESSAGE_REPLAYED: "Offline replay message replayed",
@@ -19997,17 +19970,6 @@ var init_events = __esm({
19997
19970
  SYSTEM_NOTIFICATION_ROUTED: "System notification routed",
19998
19971
  HERMES_SESSION_ROUTE_BINDING: "Hermes session route binding",
19999
19972
  DOCTOR_REPORT: "Doctor report",
20000
- // Paginated WakeupNotify recovery (BL-011) + bounded AI concurrency telemetry.
20001
- // All info-level events below must ALSO be listed in SENTRY_INFO_ALLOWLIST
20002
- // (index.ts) or info() drops them silently.
20003
- WAKEUP_PULL_STARTED: "WakeupNotify pull started",
20004
- WAKEUP_PULL_PAGE_FETCHED: "WakeupNotify pull page fetched",
20005
- WAKEUP_PULL_PAGE_RETRY: "WakeupNotify pull page retry",
20006
- WAKEUP_PULL_COMPLETED: "WakeupNotify pull completed",
20007
- WAKEUP_NOTIFICATION_REJECTED: "WakeupNotify notification rejected",
20008
- WAKEUP_CHUNK_DISPATCHED: "WakeupNotify chunk dispatched",
20009
- WAKEUP_IN_MEMORY_WORK_DROPPED: "WakeupNotify in-memory work dropped",
20010
- AI_CONCURRENCY_SNAPSHOT: "AI concurrency snapshot",
20011
19973
  // ── error ─────────────────────────────────────────────────────
20012
19974
  XMTP_CONNECTION_FAILED: "XMTP connection failed",
20013
19975
  CONVERSATIONS_STREAM_FAILED: "conversations.stream failed",
@@ -20062,7 +20024,6 @@ var init_events = __esm({
20062
20024
  AI_RUN_TOOL_FAILED: "AI run tool failed",
20063
20025
  IPC_FAILED: "IPC failed",
20064
20026
  NOTIFY_AGENTS_WAKEUP_FAILED: "Notify agents wakeup failed",
20065
- WAKEUP_PULL_FAILED: "WakeupNotify pull failed",
20066
20027
  OUTBOUND_AGENT_LOOKUP_FAILED: "Outbound agent lookup failed",
20067
20028
  OUTBOUND_ELIGIBILITY_CHECK_FAILED: "Outbound eligibility check failed",
20068
20029
  OUTBOUND_ELIGIBILITY_BYPASSED: "Outbound eligibility bypassed",
@@ -20864,15 +20825,6 @@ var init_sentry_logger = __esm({
20864
20825
  LogEvent.USER_CHANNEL_MESSAGE_DELIVERED,
20865
20826
  LogEvent.SYSTEM_NOTIFICATION_RECEIVED,
20866
20827
  LogEvent.SYSTEM_NOTIFICATION_ROUTED,
20867
- // Paginated WakeupNotify recovery (BL-011) + bounded AI concurrency telemetry.
20868
- LogEvent.WAKEUP_PULL_STARTED,
20869
- LogEvent.WAKEUP_PULL_PAGE_FETCHED,
20870
- LogEvent.WAKEUP_PULL_PAGE_RETRY,
20871
- LogEvent.WAKEUP_PULL_COMPLETED,
20872
- LogEvent.WAKEUP_NOTIFICATION_REJECTED,
20873
- LogEvent.WAKEUP_CHUNK_DISPATCHED,
20874
- LogEvent.WAKEUP_IN_MEMORY_WORK_DROPPED,
20875
- LogEvent.AI_CONCURRENCY_SNAPSHOT,
20876
20828
  LogEvent.HERMES_SESSION_ROUTE_BINDING,
20877
20829
  LogEvent.INBOUND_BLOCKED_ADDRESS_MISMATCH,
20878
20830
  LogEvent.INBOUND_BLOCKED_INELIGIBLE,
@@ -20895,6 +20847,7 @@ var init_sentry_logger = __esm({
20895
20847
  LogEvent.AGENT_STREAM_ERROR,
20896
20848
  LogEvent.AGENT_STREAM_RECOVERED,
20897
20849
  LogEvent.AGENT_STREAM_RECOVERY_REPLAY_COMPLETED,
20850
+ LogEvent.AGENT_STREAM_RECOVERY_REPLAY_TERMINATED,
20898
20851
  LogEvent.ADDRESS_SYNC_COMPLETED,
20899
20852
  LogEvent.AGENTS_REFRESHED,
20900
20853
  LogEvent.AGENTS_WAKEUP_NOTIFIED,
@@ -25288,7 +25241,7 @@ var require_websocket2 = __commonJS({
25288
25241
  var http2 = require("http");
25289
25242
  var net = require("net");
25290
25243
  var tls = require("tls");
25291
- var { randomBytes: randomBytes4, createHash: createHash7 } = require("crypto");
25244
+ var { randomBytes: randomBytes4, createHash: createHash6 } = require("crypto");
25292
25245
  var { Duplex, Readable } = require("stream");
25293
25246
  var { URL: URL2 } = require("url");
25294
25247
  var PerMessageDeflate = require_permessage_deflate();
@@ -25948,7 +25901,7 @@ var require_websocket2 = __commonJS({
25948
25901
  abortHandshake(websocket, socket, "Invalid Upgrade header");
25949
25902
  return;
25950
25903
  }
25951
- const digest = createHash7("sha1").update(key + GUID).digest("base64");
25904
+ const digest = createHash6("sha1").update(key + GUID).digest("base64");
25952
25905
  if (res.headers["sec-websocket-accept"] !== digest) {
25953
25906
  abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
25954
25907
  return;
@@ -26315,7 +26268,7 @@ var require_websocket_server = __commonJS({
26315
26268
  var EventEmitter2 = require("events");
26316
26269
  var http2 = require("http");
26317
26270
  var { Duplex } = require("stream");
26318
- var { createHash: createHash7 } = require("crypto");
26271
+ var { createHash: createHash6 } = require("crypto");
26319
26272
  var extension = require_extension();
26320
26273
  var PerMessageDeflate = require_permessage_deflate();
26321
26274
  var subprotocol = require_subprotocol();
@@ -26616,7 +26569,7 @@ var require_websocket_server = __commonJS({
26616
26569
  );
26617
26570
  }
26618
26571
  if (this._state > RUNNING) return abortHandshake(socket, 503);
26619
- const digest = createHash7("sha1").update(key + GUID).digest("base64");
26572
+ const digest = createHash6("sha1").update(key + GUID).digest("base64");
26620
26573
  const headers = [
26621
26574
  "HTTP/1.1 101 Switching Protocols",
26622
26575
  "Upgrade: websocket",
@@ -26981,7 +26934,7 @@ function buildConnectParams(config, instanceId, protocolVersion) {
26981
26934
  client: {
26982
26935
  id: "gateway-client",
26983
26936
  displayName: "okx-a2a-node",
26984
- version: "0.2.9-beta-912b775358-260824171011",
26937
+ version: "0.2.9",
26985
26938
  platform: "node",
26986
26939
  mode: "backend",
26987
26940
  instanceId
@@ -26992,7 +26945,7 @@ function buildConnectParams(config, instanceId, protocolVersion) {
26992
26945
  commands: [],
26993
26946
  permissions: {},
26994
26947
  locale: Intl.DateTimeFormat().resolvedOptions().locale || "en-US",
26995
- userAgent: `okx-a2a-node/${"0.2.9-beta-912b775358-260824171011"}`,
26948
+ userAgent: `okx-a2a-node/${"0.2.9"}`,
26996
26949
  auth: {
26997
26950
  ...config.token ? { token: config.token } : {},
26998
26951
  ...config.password ? { password: config.password } : {}
@@ -28959,7 +28912,7 @@ var init_sentry_config = __esm({
28959
28912
  environment = process.env.SENTRY_ENV === "dev" ? "dev" : "prod";
28960
28913
  SENTRY_CONFIG = {
28961
28914
  projectName: "okx/openclaw-okx-a2a-extension",
28962
- release: "0.2.9-beta-912b775358-260824171011",
28915
+ release: "0.2.9",
28963
28916
  environment,
28964
28917
  runtimeContainer: normalizeRuntimeContainer(process.env.OKX_A2A_RUNTIME_CONTAINER)
28965
28918
  };
@@ -40129,7 +40082,7 @@ async function exportDiagnosticLogs(options) {
40129
40082
  node: process.version,
40130
40083
  platform: process.platform,
40131
40084
  arch: process.arch,
40132
- packageVersion: true ? "0.2.9-beta-912b775358-260824171011" : "unknown",
40085
+ packageVersion: true ? "0.2.9" : "unknown",
40133
40086
  sensitiveContentIncluded: options.includeSensitiveContent,
40134
40087
  listenerAndLlmContentIncluded: true,
40135
40088
  credentialsAlwaysRedacted: true,
@@ -57175,6 +57128,12 @@ function replayScanBackoffMs(consecutiveFailures) {
57175
57128
  REPLAY_SCAN_MAX_BACKOFF_MS
57176
57129
  );
57177
57130
  }
57131
+ function replayScanBackoffWithJitterMs(consecutiveFailures, randomValue = Math.random()) {
57132
+ const baseMs = replayScanBackoffMs(consecutiveFailures);
57133
+ const boundedRandom = Math.min(1, Math.max(0, randomValue));
57134
+ const jitteredMs = Math.round(baseMs * (0.9 + boundedRandom * 0.2));
57135
+ return Math.min(REPLAY_SCAN_MAX_BACKOFF_MS, jitteredMs);
57136
+ }
57178
57137
  function isOfflineReplayForTrigger(trigger) {
57179
57138
  return trigger === "startup";
57180
57139
  }
@@ -57361,6 +57320,7 @@ var init_xmtp_sdk = __esm({
57361
57320
  replayScanFailuresByAddress = /* @__PURE__ */ new Map();
57362
57321
  replayScanRetryByAddress = /* @__PURE__ */ new Map();
57363
57322
  replayScanNowMs = () => Date.now();
57323
+ replayScanRandom = () => Math.random();
57364
57324
  replayScanSetTimeout = (callback, delayMs) => setTimeout(callback, delayMs);
57365
57325
  replayScanClearTimeout = (timer) => clearTimeout(timer);
57366
57326
  inboundReplayGates = /* @__PURE__ */ new Map();
@@ -57847,7 +57807,7 @@ var init_xmtp_sdk = __esm({
57847
57807
  this.clients.delete(address);
57848
57808
  this.inboundReplayGates.delete(address.toLowerCase());
57849
57809
  this.replayScanFailuresByAddress.delete(address.toLowerCase());
57850
- this.clearReplayScanRetry(address);
57810
+ this.clearReplayScanRetry(address, "client_removed");
57851
57811
  logger.info(LogEvent.AGENT_CLIENT_REMOVED, {
57852
57812
  ...agentExtras({
57853
57813
  walletAddress: address,
@@ -58063,7 +58023,7 @@ var init_xmtp_sdk = __esm({
58063
58023
  this.clients.delete(address);
58064
58024
  this.inboundReplayGates.delete(addressKey);
58065
58025
  this.replayScanFailuresByAddress.delete(addressKey);
58066
- this.clearReplayScanRetry(address);
58026
+ this.clearReplayScanRetry(address, "client_recycled");
58067
58027
  logWithTimestamp(
58068
58028
  `[xmtp-sdk] recycle: stopped client: ${address} (agentId=${agentInfo.agentId})`
58069
58029
  );
@@ -58613,7 +58573,23 @@ var init_xmtp_sdk = __esm({
58613
58573
  this.clientGenerationByClient.set(client, generation);
58614
58574
  return generation;
58615
58575
  }
58616
- clearReplayScanRetry(address) {
58576
+ logStreamRecoveryReplayTerminal(address, clientGeneration, recoveryIdentities, terminalReason) {
58577
+ for (const recoverySequence of recoveryIdentities) {
58578
+ logger.info(LogEvent.AGENT_STREAM_RECOVERY_REPLAY_TERMINATED, {
58579
+ ...agentExtras({
58580
+ walletAddress: address,
58581
+ onchainosAgentId: this.getAgentByAddress(address)?.agentId,
58582
+ role: this.getAgentByAddress(address)?.role
58583
+ }),
58584
+ clientGeneration: String(clientGeneration),
58585
+ recoverySequence,
58586
+ outcome: "terminal",
58587
+ replayOutcome: "terminated",
58588
+ terminalReason
58589
+ });
58590
+ }
58591
+ }
58592
+ clearReplayScanRetry(address, terminalReason) {
58617
58593
  const addressKey = address.toLowerCase();
58618
58594
  const scheduled = this.replayScanRetryByAddress.get(addressKey);
58619
58595
  if (!scheduled) {
@@ -58621,15 +58597,31 @@ var init_xmtp_sdk = __esm({
58621
58597
  }
58622
58598
  this.replayScanRetryByAddress.delete(addressKey);
58623
58599
  this.replayScanClearTimeout(scheduled.timer);
58600
+ if (terminalReason) {
58601
+ this.logStreamRecoveryReplayTerminal(
58602
+ address,
58603
+ scheduled.clientGeneration,
58604
+ scheduled.recoveryIdentities,
58605
+ terminalReason
58606
+ );
58607
+ }
58624
58608
  }
58625
- scheduleReplayScanRetry(address, expectedClient, clientGeneration, retryTrigger, delayMs) {
58609
+ scheduleReplayScanRetry(address, expectedClient, clientGeneration, retryTrigger, delayMs, recoveryIdentities = []) {
58626
58610
  const addressKey = address.toLowerCase();
58627
58611
  const scheduled = this.replayScanRetryByAddress.get(addressKey);
58628
58612
  if (scheduled?.clientGeneration === clientGeneration) {
58613
+ if (retryTrigger === "stream_recovery") {
58614
+ scheduled.retryTrigger = retryTrigger;
58615
+ for (const recoveryIdentity of recoveryIdentities) {
58616
+ if (!scheduled.recoveryIdentities.includes(recoveryIdentity)) {
58617
+ scheduled.recoveryIdentities.push(recoveryIdentity);
58618
+ }
58619
+ }
58620
+ }
58629
58621
  return;
58630
58622
  }
58631
58623
  if (scheduled) {
58632
- this.clearReplayScanRetry(address);
58624
+ this.clearReplayScanRetry(address, "client_replaced");
58633
58625
  }
58634
58626
  const timer = this.replayScanSetTimeout(() => {
58635
58627
  const current = this.replayScanRetryByAddress.get(addressKey);
@@ -58638,12 +58630,18 @@ var init_xmtp_sdk = __esm({
58638
58630
  }
58639
58631
  this.replayScanRetryByAddress.delete(addressKey);
58640
58632
  if (this.clients.get(address) !== expectedClient || this.stoppedAddresses.has(addressKey)) {
58633
+ this.logStreamRecoveryReplayTerminal(
58634
+ address,
58635
+ current.clientGeneration,
58636
+ current.recoveryIdentities,
58637
+ this.stoppedAddresses.has(addressKey) ? "client_stopped" : "client_replaced"
58638
+ );
58641
58639
  return;
58642
58640
  }
58643
58641
  void this.replayOfflineMessagesForAddressSingleFlight(
58644
58642
  address,
58645
- retryTrigger,
58646
- void 0,
58643
+ current.retryTrigger,
58644
+ current.recoveryIdentities.at(-1),
58647
58645
  expectedClient
58648
58646
  ).catch((err2) => {
58649
58647
  logWithTimestamp(
@@ -58664,18 +58662,41 @@ var init_xmtp_sdk = __esm({
58664
58662
  timer.unref?.();
58665
58663
  this.replayScanRetryByAddress.set(addressKey, {
58666
58664
  clientGeneration,
58665
+ retryTrigger,
58666
+ recoveryIdentities: retryTrigger === "stream_recovery" ? [...new Set(recoveryIdentities)] : [],
58667
58667
  timer
58668
58668
  });
58669
58669
  }
58670
+ notifyAgentsWakeupAfterReplay() {
58671
+ const notifyAgentsWakeup2 = this.tools.notifyAgentsWakeup;
58672
+ const agentIds = this.allAgents.map((agent) => agent.agentId);
58673
+ if (!notifyAgentsWakeup2 || agentIds.length === 0) {
58674
+ return;
58675
+ }
58676
+ void notifyAgentsWakeup2(agentIds).then(() => {
58677
+ logger.info(LogEvent.AGENTS_WAKEUP_NOTIFIED, {
58678
+ count: String(agentIds.length),
58679
+ onchainosAgentIds: agentIds.join(","),
58680
+ stage: "after-startup-replay"
58681
+ });
58682
+ }).catch((err2) => {
58683
+ logWithTimestamp("[xmtp-sdk] notifyAgentsWakeup unexpected error:", err2);
58684
+ logger.error(
58685
+ LogEvent.NOTIFY_AGENTS_WAKEUP_FAILED,
58686
+ err2 instanceof Error ? err2 : new Error(String(err2)),
58687
+ {
58688
+ count: String(agentIds.length),
58689
+ stage: "after-startup-replay"
58690
+ }
58691
+ );
58692
+ });
58693
+ }
58670
58694
  /**
58671
58695
  * Completes the startup handoff from stored history to the live stream.
58672
58696
  * Listeners are already attached, but their host handlers stay buffered
58673
- * until replay finishes and the buffer is drained.
58674
- *
58675
- * Telling the backend the agents are awake is deliberately NOT done here.
58676
- * The daemon (listener.ts) runs the paginated task-wakeup pull AFTER the bounded
58677
- * command processor is ready, so wakeup-triggered work cannot be dispatched
58678
- * before the processor exists.
58697
+ * until replay finishes and the buffer is drained. Only then do we tell
58698
+ * the backend that the agents are awake, so wakeup-triggered messages
58699
+ * cannot overtake the stored backlog.
58679
58700
  */
58680
58701
  async completeStartupReplay() {
58681
58702
  const startupGates = new Map(
@@ -58690,6 +58711,7 @@ var init_xmtp_sdk = __esm({
58690
58711
  }
58691
58712
  this.resolveStartupReplayCompletion?.();
58692
58713
  this.resolveStartupReplayCompletion = void 0;
58714
+ this.notifyAgentsWakeupAfterReplay();
58693
58715
  return summary;
58694
58716
  }
58695
58717
  async startListeningForAddresses(addresses) {
@@ -58928,7 +58950,7 @@ var init_xmtp_sdk = __esm({
58928
58950
  String(recovery.recoverySequence),
58929
58951
  agent
58930
58952
  );
58931
- if (summary.outcome === "completed" && !recoveryDisposed && this.clients.get(address) === agent) {
58953
+ if (summary.outcome === "completed" && summary.consecutiveFailures === void 0 && !recoveryDisposed && this.clients.get(address) === agent) {
58932
58954
  logger.info(LogEvent.AGENT_STREAM_RECOVERY_REPLAY_COMPLETED, {
58933
58955
  ...agentExtras(identity),
58934
58956
  clientGeneration: String(clientGeneration),
@@ -59025,10 +59047,16 @@ var init_xmtp_sdk = __esm({
59025
59047
  let priorFailure = this.replayScanFailuresByAddress.get(addressKey);
59026
59048
  if (priorFailure && priorFailure.clientGeneration !== clientGeneration) {
59027
59049
  this.replayScanFailuresByAddress.delete(addressKey);
59028
- this.clearReplayScanRetry(address);
59050
+ this.clearReplayScanRetry(address, "client_replaced");
59029
59051
  priorFailure = void 0;
59030
59052
  }
59031
59053
  if (priorFailure && attemptNowMs < priorFailure.nextAttemptAtMs) {
59054
+ if (trigger === "stream_recovery") {
59055
+ priorFailure.retryTrigger = trigger;
59056
+ if (recoveryIdentity && !priorFailure.recoveryIdentities.includes(recoveryIdentity)) {
59057
+ priorFailure.recoveryIdentities.push(recoveryIdentity);
59058
+ }
59059
+ }
59032
59060
  priorFailure.suppressedAttempts++;
59033
59061
  summary.outcome = "suppressed_backoff";
59034
59062
  summary.failureStage = priorFailure.lastFailureStage;
@@ -59045,7 +59073,8 @@ var init_xmtp_sdk = __esm({
59045
59073
  agent,
59046
59074
  clientGeneration,
59047
59075
  priorFailure.retryTrigger,
59048
- summary.backoffMs
59076
+ summary.backoffMs,
59077
+ priorFailure.recoveryIdentities
59049
59078
  );
59050
59079
  summary.durationMs = Date.now() - addressReplayStartedAt;
59051
59080
  return summary;
@@ -59058,15 +59087,23 @@ var init_xmtp_sdk = __esm({
59058
59087
  const recordScanFailure = (stage, err2) => {
59059
59088
  const previous = this.replayScanFailuresByAddress.get(addressKey);
59060
59089
  const consecutiveFailures = (previous?.consecutiveFailures ?? 0) + 1;
59061
- const backoffMs = replayScanBackoffMs(consecutiveFailures);
59090
+ const backoffMs = replayScanBackoffWithJitterMs(
59091
+ consecutiveFailures,
59092
+ this.replayScanRandom()
59093
+ );
59062
59094
  const suppressedAttempts = previous?.suppressedAttempts ?? 0;
59063
59095
  const failureNowMs = this.replayScanNowMs();
59064
- const retryTrigger = isOfflineReplayForTrigger(trigger) ? "startup" : "periodic_repair";
59096
+ const recoveryIdentities = [...previous?.recoveryIdentities ?? []];
59097
+ if (trigger === "stream_recovery" && recoveryIdentity && !recoveryIdentities.includes(recoveryIdentity)) {
59098
+ recoveryIdentities.push(recoveryIdentity);
59099
+ }
59100
+ const retryTrigger = trigger === "stream_recovery" ? trigger : previous?.retryTrigger ?? trigger;
59065
59101
  this.replayScanFailuresByAddress.set(addressKey, {
59066
59102
  clientGeneration,
59067
59103
  consecutiveFailures,
59068
59104
  nextAttemptAtMs: failureNowMs + backoffMs,
59069
59105
  retryTrigger,
59106
+ recoveryIdentities,
59070
59107
  suppressedAttempts: 0,
59071
59108
  lastFailureStage: stage
59072
59109
  });
@@ -59075,7 +59112,8 @@ var init_xmtp_sdk = __esm({
59075
59112
  agent,
59076
59113
  clientGeneration,
59077
59114
  retryTrigger,
59078
- backoffMs
59115
+ backoffMs,
59116
+ recoveryIdentities
59079
59117
  );
59080
59118
  summary.outcome = stage === "syncAll" ? "sync_failed" : "list_failed";
59081
59119
  summary.failureStage = stage;
@@ -59272,6 +59310,30 @@ var init_xmtp_sdk = __esm({
59272
59310
  recoveredAfterFailures: String(recoveredFailure?.consecutiveFailures ?? 0),
59273
59311
  suppressedAttempts: String(recoveredFailure?.suppressedAttempts ?? 0)
59274
59312
  });
59313
+ if (recoveredFailure) {
59314
+ for (const recoverySequence of recoveredFailure.recoveryIdentities) {
59315
+ logger.info(LogEvent.AGENT_STREAM_RECOVERY_REPLAY_COMPLETED, {
59316
+ ...agentExtras({
59317
+ walletAddress: address,
59318
+ inboxId: agent.client?.inboxId,
59319
+ onchainosAgentId: this.getAgentByAddress(address)?.agentId,
59320
+ role: this.getAgentByAddress(address)?.role
59321
+ }),
59322
+ clientGeneration: String(clientGeneration),
59323
+ recoverySequence,
59324
+ replayed: String(summary.replayed),
59325
+ skipped: String(summary.skipped),
59326
+ conversationCount: String(summary.conversations),
59327
+ replayDurationMs: String(Date.now() - addressReplayStartedAt),
59328
+ outcome: "success",
59329
+ replayOutcome: "completed",
59330
+ recoveredAfterFailures: String(
59331
+ recoveredFailure.consecutiveFailures
59332
+ ),
59333
+ suppressedAttempts: String(recoveredFailure.suppressedAttempts)
59334
+ });
59335
+ }
59336
+ }
59275
59337
  summary.outcome = "completed";
59276
59338
  summary.consecutiveFailures = recoveredFailure?.consecutiveFailures;
59277
59339
  summary.suppressedAttempts = recoveredFailure?.suppressedAttempts;
@@ -59928,6 +59990,39 @@ function fingerprintAgents(agents) {
59928
59990
  function filterNoisyAgentIdentityLog(stderr) {
59929
59991
  return stderr.split(/\r?\n/).filter((line) => !line.includes("[agent-identity] get response")).join("\n").trim();
59930
59992
  }
59993
+ function previewLogText(value, max = 300) {
59994
+ const normalized = value.replace(/\s+/g, " ").trim();
59995
+ return normalized.length > max ? `${normalized.slice(0, max)}...` : normalized;
59996
+ }
59997
+ async function notifyAgentsWakeup(agentIds) {
59998
+ if (agentIds.length === 0) {
59999
+ logWithTimestamp("[onchainos] wakeup-notify: agentIds empty, skipping");
60000
+ return;
60001
+ }
60002
+ const ids = agentIds.join(",");
60003
+ logWithTimestamp(`[onchainos] sending wakeup-notify (agent-ids=${ids})`);
60004
+ try {
60005
+ const { stdout, stderr } = await exec([
60006
+ "agent",
60007
+ "wakeup-notify",
60008
+ "--agent-ids",
60009
+ ids
60010
+ ]);
60011
+ if (stderr) {
60012
+ logWithTimestamp(`[onchainos] stderr (wakeup-notify): ${stderr}`);
60013
+ }
60014
+ logWithTimestamp(
60015
+ `[onchainos] wakeup-notify result agentIds=${ids} stdoutBytes=${Buffer.byteLength(stdout ?? "", "utf8")} stdoutPreview=${previewLogText(stdout ?? "")}`
60016
+ );
60017
+ logWithTimestamp(`[onchainos] wakeup-notify succeeded (agent-ids=${ids})`);
60018
+ } catch (err2) {
60019
+ guardCatchSessionExpired2(err2, "wakeup-notify");
60020
+ logWithTimestamp(
60021
+ `[onchainos] wakeup-notify failed (agent-ids=${ids}):`,
60022
+ err2?.message ?? err2
60023
+ );
60024
+ }
60025
+ }
59931
60026
  async function sendHeartbeat(chainIndex) {
59932
60027
  logWithTimestamp(`[onchainos] sending heartbeat (chain-index=${chainIndex})`);
59933
60028
  try {
@@ -65189,29 +65284,6 @@ var init_xmtp_debug = __esm({
65189
65284
  }
65190
65285
  });
65191
65286
 
65192
- // src/ai-concurrency-config.ts
65193
- function resolveMaxActiveAiExecutions(env = process.env) {
65194
- const raw = env.OKX_A2A_MAX_ACTIVE_AI_EXECUTIONS ?? env.OKX_AGENT_TASK_MAX_ACTIVE_AI_EXECUTIONS;
65195
- if (raw === void 0 || raw.trim() === "") {
65196
- return { limit: DEFAULT_MAX_ACTIVE_AI_EXECUTIONS, anomaly: null };
65197
- }
65198
- const parsed = Number(raw);
65199
- if (Number.isFinite(parsed) && Number.isInteger(parsed) && parsed > 0) {
65200
- return { limit: parsed, anomaly: null };
65201
- }
65202
- return {
65203
- limit: DEFAULT_MAX_ACTIVE_AI_EXECUTIONS,
65204
- anomaly: `invalid value "${raw}", using default ${DEFAULT_MAX_ACTIVE_AI_EXECUTIONS}`
65205
- };
65206
- }
65207
- var DEFAULT_MAX_ACTIVE_AI_EXECUTIONS;
65208
- var init_ai_concurrency_config = __esm({
65209
- "src/ai-concurrency-config.ts"() {
65210
- "use strict";
65211
- DEFAULT_MAX_ACTIVE_AI_EXECUTIONS = 4;
65212
- }
65213
- });
65214
-
65215
65287
  // src/command-processor.ts
65216
65288
  function commandSentryExtra(command, extra = {}) {
65217
65289
  const base = {
@@ -65261,17 +65333,6 @@ function startCommandProcessor(params) {
65261
65333
  const executionTimeoutMs = readPositiveEnv("OKX_A2A_COMMAND_EXECUTION_TIMEOUT_MS", DEFAULT_COMMAND_EXECUTION_TIMEOUT_MS);
65262
65334
  const staleTimeoutMs = readPositiveEnv("OKX_A2A_COMMAND_STALE_TIMEOUT_MS", DEFAULT_COMMAND_STALE_TIMEOUT_MS);
65263
65335
  const aiStaleTimeoutMs = readPositiveEnv("OKX_A2A_AI_COMMAND_STALE_TIMEOUT_MS", DEFAULT_AI_COMMAND_STALE_TIMEOUT_MS);
65264
- const { limit: maxActiveAiExecutions, anomaly: aiLimitAnomaly } = resolveMaxActiveAiExecutions(process.env);
65265
- if (aiLimitAnomaly) {
65266
- logWithTimestamp(`[okx-agent-task] AI concurrency limit config anomaly: ${aiLimitAnomaly}`);
65267
- logger.info(LogEvent.AI_CONCURRENCY_SNAPSHOT, {
65268
- component: "node_command_processor",
65269
- stage: "config",
65270
- reason: "invalid_config_using_default",
65271
- configuredLimit: String(maxActiveAiExecutions),
65272
- anomaly: aiLimitAnomaly
65273
- });
65274
- }
65275
65336
  let inFlight = false;
65276
65337
  let aiScanInFlight = false;
65277
65338
  const activeAiQueueKeys = /* @__PURE__ */ new Set();
@@ -65361,9 +65422,6 @@ function startCommandProcessor(params) {
65361
65422
  inFlight = false;
65362
65423
  }
65363
65424
  };
65364
- const AI_SNAPSHOT_MIN_INTERVAL_MS = 15e3;
65365
- let lastAiSnapshotSignature = "";
65366
- let lastAiSnapshotAtMs = 0;
65367
65425
  const aiTick = async () => {
65368
65426
  if (aiScanInFlight) {
65369
65427
  return;
@@ -65376,33 +65434,15 @@ function startCommandProcessor(params) {
65376
65434
  skipCommandIds: activeAiCommandIds
65377
65435
  });
65378
65436
  const pending = await commands.listPendingEntries();
65379
- const pendingAi = pending.filter((entry) => isAiDispatchCommand(entry.command));
65380
- if (activeAiCommandIds.size > 0 || pendingAi.length > 0) {
65381
- const snapshotNow = Date.now();
65382
- const oldestQueuedAgeMs = pendingAi.reduce((oldest, entry) => {
65383
- const createdAt = Number.isFinite(entry.command.createdAt) ? entry.command.createdAt : entry.mtimeMs;
65384
- return Math.max(oldest, snapshotNow - createdAt);
65385
- }, 0);
65386
- const snapshotSignature = `${maxActiveAiExecutions}|${activeAiCommandIds.size}|${pendingAi.length}`;
65387
- if (snapshotSignature !== lastAiSnapshotSignature || snapshotNow - lastAiSnapshotAtMs >= AI_SNAPSHOT_MIN_INTERVAL_MS) {
65388
- lastAiSnapshotSignature = snapshotSignature;
65389
- lastAiSnapshotAtMs = snapshotNow;
65390
- logger.info(LogEvent.AI_CONCURRENCY_SNAPSHOT, {
65391
- component: "node_command_processor",
65392
- configuredLimit: String(maxActiveAiExecutions),
65393
- activeCount: String(activeAiCommandIds.size),
65394
- queueDepth: String(pendingAi.length),
65395
- oldestQueuedAgeMs: String(oldestQueuedAgeMs)
65396
- });
65397
- }
65398
- } else {
65399
- lastAiSnapshotSignature = "";
65400
- }
65401
65437
  for (const entry of pending) {
65402
65438
  const command = entry.command;
65403
65439
  if (!isAiDispatchCommand(command)) {
65404
65440
  continue;
65405
65441
  }
65442
+ const queueKey = buildAiCommandQueueKey(command);
65443
+ if (activeAiQueueKeys.has(queueKey)) {
65444
+ continue;
65445
+ }
65406
65446
  if (isStalePending(entry, aiStaleTimeoutMs)) {
65407
65447
  const message = `${command.type}/${command.kind} command expired after ${formatDuration2(Date.now() - command.createdAt)} in pending queue`;
65408
65448
  await commands.completePending(command, {
@@ -65413,20 +65453,13 @@ function startCommandProcessor(params) {
65413
65453
  stage: "pending",
65414
65454
  ageMs: Date.now() - command.createdAt,
65415
65455
  timeoutMs: aiStaleTimeoutMs,
65416
- reason: "queue_expired"
65456
+ reason: "pending_expired"
65417
65457
  }));
65418
65458
  logWithTimestamp(
65419
65459
  `[okx-agent-task] ${command.type}/${command.kind} command expired id=${command.id}: ${message}`
65420
65460
  );
65421
65461
  continue;
65422
65462
  }
65423
- if (activeAiCommandIds.size >= maxActiveAiExecutions) {
65424
- continue;
65425
- }
65426
- const queueKey = buildAiCommandQueueKey(command);
65427
- if (activeAiQueueKeys.has(queueKey)) {
65428
- continue;
65429
- }
65430
65463
  const processingPath = await commands.take(command);
65431
65464
  if (!processingPath) {
65432
65465
  continue;
@@ -65999,9 +66032,6 @@ function isStalePending(entry, staleTimeoutMs) {
65999
66032
  return Date.now() - createdAt > staleTimeoutMs;
66000
66033
  }
66001
66034
  function buildAiCommandQueueKey(command) {
66002
- if (command.jobId) {
66003
- return `job:${command.jobId}`;
66004
- }
66005
66035
  if (command.kind === "job-message") {
66006
66036
  return buildDispatchSessionKey(command.jobId, command.sessionAgentId);
66007
66037
  }
@@ -66109,7 +66139,6 @@ var init_command_processor = __esm({
66109
66139
  init_user_attention_ipc();
66110
66140
  init_sentry_logger();
66111
66141
  init_xmtp_debug();
66112
- init_ai_concurrency_config();
66113
66142
  DEFAULT_COMMAND_EXECUTION_TIMEOUT_MS = 5e4;
66114
66143
  DEFAULT_COMMAND_STALE_TIMEOUT_MS = 12e4;
66115
66144
  DEFAULT_AI_COMMAND_STALE_TIMEOUT_MS = 30 * 6e4;
@@ -67710,575 +67739,6 @@ var init_message_handler = __esm({
67710
67739
  }
67711
67740
  });
67712
67741
 
67713
- // src/wakeup-notify-client.ts
67714
- function isTransientTransportError(err2) {
67715
- const message = err2 instanceof Error ? err2.message : String(err2);
67716
- return TRANSIENT_TRANSPORT_PATTERN.test(message);
67717
- }
67718
- function isPlainObject4(value) {
67719
- return !!value && typeof value === "object" && !Array.isArray(value);
67720
- }
67721
- function isValidWakeupItem(raw) {
67722
- if (!isPlainObject4(raw)) {
67723
- return { ok: false, reason: "malformed_item" };
67724
- }
67725
- if (typeof raw.agentId !== "string" || raw.agentId.length === 0) {
67726
- return { ok: false, reason: "missing_agent_id" };
67727
- }
67728
- const message = raw.message;
67729
- if (!isPlainObject4(message) || message.source !== "system") {
67730
- return { ok: false, reason: "not_system_notification" };
67731
- }
67732
- if (message.event !== "wakeup_notify") {
67733
- return { ok: false, reason: "not_wakeup_notify" };
67734
- }
67735
- return {
67736
- ok: true,
67737
- item: { agentId: raw.agentId, message }
67738
- };
67739
- }
67740
- function canonicalize(value) {
67741
- if (Array.isArray(value)) {
67742
- return value.map(canonicalize);
67743
- }
67744
- if (value && typeof value === "object") {
67745
- const source = value;
67746
- return Object.keys(source).sort().reduce((acc, key) => {
67747
- acc[key] = canonicalize(source[key]);
67748
- return acc;
67749
- }, {});
67750
- }
67751
- return value;
67752
- }
67753
- function deriveWakeupDedupeKey(item) {
67754
- const canonicalMessage = JSON.stringify(canonicalize(item.message ?? {}));
67755
- const identity = `${item.agentId}
67756
- ${canonicalMessage}`;
67757
- return `wakeup:${(0, import_node_crypto15.createHash)("sha256").update(identity).digest("hex").slice(0, 24)}`;
67758
- }
67759
- async function fetchAllWakeupNotifications(opts) {
67760
- const { agentIds, fetchPage, onPage } = opts;
67761
- const maxPages = opts.maxPages;
67762
- const maxPageAttempts = opts.maxPageAttempts ?? DEFAULT_MAX_PAGE_ATTEMPTS;
67763
- const retryDelayMs = opts.retryDelayMs ?? DEFAULT_PAGE_RETRY_DELAY_MS;
67764
- const sleep5 = opts.sleep ?? ((ms) => new Promise((resolve14) => setTimeout(resolve14, ms)));
67765
- const isRetryableError = opts.isRetryableError ?? isTransientTransportError;
67766
- const onRetry = opts.onRetry;
67767
- const fetchPageWithRetry = async (pageNum) => {
67768
- let attempt = 0;
67769
- while (true) {
67770
- attempt++;
67771
- try {
67772
- return await fetchPage({ agentIds, page: pageNum });
67773
- } catch (err2) {
67774
- if (!isRetryableError(err2) || attempt >= maxPageAttempts) {
67775
- throw err2;
67776
- }
67777
- onRetry?.({ page: pageNum, attempt, reason: "transient_transport" });
67778
- await sleep5(retryDelayMs * attempt + Math.floor(Math.random() * (retryDelayMs + 1)));
67779
- }
67780
- }
67781
- };
67782
- const items = [];
67783
- const rejects = [];
67784
- const visited = /* @__PURE__ */ new Set();
67785
- let pagesFetched = 0;
67786
- let page = 1;
67787
- let terminated = "empty";
67788
- try {
67789
- while (true) {
67790
- const resp = await fetchPageWithRetry(page);
67791
- pagesFetched++;
67792
- if (resp.code !== 0) {
67793
- terminated = "business_error";
67794
- break;
67795
- }
67796
- const rawList = resp.data?.list;
67797
- if (!Array.isArray(rawList)) {
67798
- rejects.push({ reason: "invalid_response_list" });
67799
- terminated = "invalid_response";
67800
- break;
67801
- }
67802
- const list = rawList;
67803
- let itemCount = 0;
67804
- let rejectedCount = 0;
67805
- for (const element of list) {
67806
- const check = isValidWakeupItem(element);
67807
- if (check.ok) {
67808
- items.push(check.item);
67809
- itemCount++;
67810
- } else {
67811
- rejects.push({ reason: check.reason });
67812
- rejectedCount++;
67813
- }
67814
- }
67815
- const nextPage = resp.data?.nextPage;
67816
- onPage?.({ page, itemCount, rejectedCount, hasNextPage: nextPage != null });
67817
- if (nextPage === null) {
67818
- terminated = items.length || rejects.length ? "next_page_null" : "empty";
67819
- break;
67820
- }
67821
- if (typeof nextPage !== "number" || !Number.isInteger(nextPage) || nextPage <= 0) {
67822
- rejects.push({ reason: "invalid_next_page" });
67823
- terminated = "invalid_response";
67824
- break;
67825
- }
67826
- visited.add(page);
67827
- page = nextPage;
67828
- if (visited.has(page) || maxPages !== void 0 && pagesFetched >= maxPages) {
67829
- terminated = "max_pages";
67830
- break;
67831
- }
67832
- }
67833
- } catch {
67834
- terminated = "transport_error";
67835
- }
67836
- const summary = {
67837
- pagesFetched,
67838
- received: items.length + rejects.length,
67839
- persisted: 0,
67840
- partial: 0,
67841
- duplicates: 0,
67842
- rejected: rejects.length,
67843
- terminated
67844
- };
67845
- return { items, summary, rejects };
67846
- }
67847
- var import_node_crypto15, DEFAULT_MAX_PAGE_ATTEMPTS, DEFAULT_PAGE_RETRY_DELAY_MS, TRANSIENT_TRANSPORT_PATTERN;
67848
- var init_wakeup_notify_client = __esm({
67849
- "src/wakeup-notify-client.ts"() {
67850
- "use strict";
67851
- import_node_crypto15 = require("node:crypto");
67852
- DEFAULT_MAX_PAGE_ATTEMPTS = 3;
67853
- DEFAULT_PAGE_RETRY_DELAY_MS = 500;
67854
- TRANSIENT_TRANSPORT_PATTERN = /timed out|timeout|ETIMEDOUT|ECONNRESET|ECONNREFUSED|ENOTFOUND|EAI_AGAIN|socket hang up|network/i;
67855
- }
67856
- });
67857
-
67858
- // src/wakeup-notify-ingest.ts
67859
- async function ingestWakeupNotification(item, deps) {
67860
- const messageId = deriveWakeupDedupeKey(item);
67861
- const itemJobId = item.message.jobId ?? null;
67862
- const rawText = JSON.stringify({ agentId: item.agentId, message: item.message });
67863
- const notif = extractSystemNotification(JSON.parse(rawText));
67864
- if (!notif?.agentId) {
67865
- return {
67866
- status: "rejected",
67867
- reason: "invalid_system_notification",
67868
- dedupeKey: messageId,
67869
- jobId: itemJobId,
67870
- targetCount: 0
67871
- };
67872
- }
67873
- const targets = resolveSystemNotificationTargets(
67874
- { sessionStore: deps.sessionStore, myXmtpAddress: deps.myXmtpAddress ?? "", store: void 0 },
67875
- notif
67876
- );
67877
- let succeeded = 0;
67878
- let failed = 0;
67879
- for (const target of targets) {
67880
- let enqueued = false;
67881
- for (let attempt = 1; attempt <= MAX_TARGET_ENQUEUE_ATTEMPTS && !enqueued; attempt++) {
67882
- try {
67883
- await enqueueAiSessionMessageDispatch({
67884
- commands: deps.commands,
67885
- event: {
67886
- sessionKey: target.sessionKey,
67887
- content: rawText,
67888
- messageId,
67889
- jobId: target.jobId ?? null,
67890
- agentId: target.agentId ?? null
67891
- }
67892
- });
67893
- enqueued = true;
67894
- } catch {
67895
- }
67896
- }
67897
- if (enqueued) {
67898
- succeeded += 1;
67899
- } else {
67900
- failed += 1;
67901
- }
67902
- }
67903
- if (targets.length > 0 && succeeded === 0) {
67904
- return {
67905
- status: "rejected",
67906
- reason: "enqueue_failed",
67907
- dedupeKey: messageId,
67908
- jobId: notif.jobId ?? null,
67909
- targetCount: 0,
67910
- failedTargetCount: failed
67911
- };
67912
- }
67913
- if (failed > 0) {
67914
- return {
67915
- status: "partial",
67916
- reason: "partial_enqueue",
67917
- dedupeKey: messageId,
67918
- jobId: notif.jobId ?? null,
67919
- targetCount: succeeded,
67920
- failedTargetCount: failed
67921
- };
67922
- }
67923
- return {
67924
- status: "persisted",
67925
- dedupeKey: messageId,
67926
- jobId: notif.jobId ?? null,
67927
- targetCount: succeeded
67928
- };
67929
- }
67930
- var MAX_TARGET_ENQUEUE_ATTEMPTS;
67931
- var init_wakeup_notify_ingest = __esm({
67932
- "src/wakeup-notify-ingest.ts"() {
67933
- "use strict";
67934
- init_ai_dispatch_queue();
67935
- init_message_handler();
67936
- init_wakeup_notify_client();
67937
- MAX_TARGET_ENQUEUE_ATTEMPTS = 3;
67938
- }
67939
- });
67940
-
67941
- // src/wakeup-notify-transport.ts
67942
- function withTimeout3(promise, timeoutMs, label) {
67943
- return new Promise((resolve14, reject) => {
67944
- const timer = setTimeout(() => {
67945
- reject(new Error(`${label} timed out after ${timeoutMs}ms`));
67946
- }, timeoutMs);
67947
- promise.then(
67948
- (value) => {
67949
- clearTimeout(timer);
67950
- resolve14(value);
67951
- },
67952
- (err2) => {
67953
- clearTimeout(timer);
67954
- reject(err2);
67955
- }
67956
- );
67957
- });
67958
- }
67959
- function resolveCliTimeoutMs(override) {
67960
- if (typeof override === "number" && Number.isFinite(override) && override > 0) {
67961
- return override;
67962
- }
67963
- const raw = Number(process.env.OKX_A2A_WAKEUP_CLI_TIMEOUT_MS);
67964
- return Number.isFinite(raw) && raw > 0 ? raw : DEFAULT_CLI_TIMEOUT_MS;
67965
- }
67966
- function isPlainObject5(value) {
67967
- return !!value && typeof value === "object" && !Array.isArray(value);
67968
- }
67969
- function mapCliStdoutToWakeupResponse(parsed) {
67970
- const root = isPlainObject5(parsed) ? parsed : {};
67971
- const rootData = isPlainObject5(root.data) ? root.data : {};
67972
- const nestedData = isPlainObject5(rootData.data) ? rootData.data : {};
67973
- const candidates = [root, rootData, nestedData];
67974
- let code;
67975
- let msg;
67976
- let list = [];
67977
- let listFound = false;
67978
- let nextPage = null;
67979
- let nextPageFound = false;
67980
- for (const candidate of candidates) {
67981
- if (code === void 0 && typeof candidate.code === "number" && Number.isFinite(candidate.code)) {
67982
- code = candidate.code;
67983
- }
67984
- if (msg === void 0 && typeof candidate.msg === "string") {
67985
- msg = candidate.msg;
67986
- }
67987
- if (!listFound && Array.isArray(candidate.list)) {
67988
- list = candidate.list;
67989
- listFound = true;
67990
- }
67991
- if (!nextPageFound && "nextPage" in candidate) {
67992
- const raw = candidate.nextPage;
67993
- if (typeof raw === "number" && Number.isFinite(raw)) {
67994
- nextPage = raw;
67995
- nextPageFound = true;
67996
- } else if (raw === null) {
67997
- nextPage = null;
67998
- nextPageFound = true;
67999
- }
68000
- }
68001
- }
68002
- if (code === void 0) {
68003
- code = root.ok === true ? 0 : 1;
68004
- }
68005
- return {
68006
- code,
68007
- msg,
68008
- data: { list: listFound ? list : void 0, nextPage: nextPageFound ? nextPage : void 0 }
68009
- };
68010
- }
68011
- function createOnchainosWakeupFetchPage(deps = {}) {
68012
- const timeoutMs = resolveCliTimeoutMs(deps.timeoutMs);
68013
- const exec2 = deps.exec ?? ((args) => exec(args, { timeoutMs }));
68014
- return async ({ agentIds, page }) => {
68015
- const { stdout } = await withTimeout3(
68016
- exec2([
68017
- "agent",
68018
- TASK_WAKEUP_CLI_COMMAND,
68019
- "--agent-ids",
68020
- agentIds.join(","),
68021
- "--page",
68022
- String(page)
68023
- ]),
68024
- timeoutMs,
68025
- `onchainos ${TASK_WAKEUP_CLI_COMMAND}`
68026
- );
68027
- const parsed = parseCliJson(stdout, TASK_WAKEUP_CLI_COMMAND, {
68028
- page: String(page)
68029
- });
68030
- return mapCliStdoutToWakeupResponse(parsed);
68031
- };
68032
- }
68033
- var TASK_WAKEUP_CLI_COMMAND, DEFAULT_CLI_TIMEOUT_MS;
68034
- var init_wakeup_notify_transport = __esm({
68035
- "src/wakeup-notify-transport.ts"() {
68036
- "use strict";
68037
- init_bin();
68038
- init_cli_response();
68039
- TASK_WAKEUP_CLI_COMMAND = "task-wakeup";
68040
- DEFAULT_CLI_TIMEOUT_MS = 3e4;
68041
- }
68042
- });
68043
-
68044
- // src/wakeup-chunk-config.ts
68045
- function resolveWakeupChunkSize(env = process.env) {
68046
- const fallback = resolveMaxActiveAiExecutions(env).limit;
68047
- const raw = env.OKX_A2A_WAKEUP_CHUNK_SIZE;
68048
- if (raw === void 0 || raw.trim() === "") {
68049
- return { chunkSize: fallback, anomaly: null };
68050
- }
68051
- const parsed = Number(raw);
68052
- if (Number.isFinite(parsed) && Number.isInteger(parsed) && parsed > 0) {
68053
- return { chunkSize: parsed, anomaly: null };
68054
- }
68055
- return {
68056
- chunkSize: fallback,
68057
- anomaly: `invalid value "${raw}", using default ${fallback}`
68058
- };
68059
- }
68060
- var init_wakeup_chunk_config = __esm({
68061
- "src/wakeup-chunk-config.ts"() {
68062
- "use strict";
68063
- init_ai_concurrency_config();
68064
- }
68065
- });
68066
-
68067
- // src/wakeup-pull.ts
68068
- function splitIntoChunks(items, size3) {
68069
- const chunkSize = Math.max(1, size3);
68070
- const chunks = [];
68071
- for (let i = 0; i < items.length; i += chunkSize) {
68072
- chunks.push(items.slice(i, i + chunkSize));
68073
- }
68074
- return chunks;
68075
- }
68076
- function buildDroppedWorkTelemetry(snapshot) {
68077
- return {
68078
- sentry: {
68079
- component: "wakeup_pull",
68080
- reason: "daemon_shutdown",
68081
- remainingChunks: String(snapshot.remainingChunks),
68082
- droppedMessages: String(snapshot.droppedMessages),
68083
- affectedJobCount: String(snapshot.pendingJobIds.length),
68084
- inFlightChunk: String(snapshot.inFlightChunk)
68085
- },
68086
- local: {
68087
- droppedMessages: snapshot.droppedMessages,
68088
- pendingJobIds: snapshot.pendingJobIds.slice(0, MAX_LOGGED_PENDING_JOB_IDS),
68089
- jobIdsTruncated: snapshot.pendingJobIds.length > MAX_LOGGED_PENDING_JOB_IDS,
68090
- inFlightChunk: snapshot.inFlightChunk
68091
- }
68092
- };
68093
- }
68094
- function logDroppedWakeupWorkOnShutdown(dispatcher) {
68095
- if (!dispatcher) {
68096
- return;
68097
- }
68098
- const snapshot = dispatcher.pendingSnapshot();
68099
- if (snapshot.droppedMessages === 0 && !snapshot.inFlightChunk) {
68100
- return;
68101
- }
68102
- const telemetry = buildDroppedWorkTelemetry(snapshot);
68103
- logger.info(LogEvent.WAKEUP_IN_MEMORY_WORK_DROPPED, telemetry.sentry);
68104
- logWithTimestamp("[okx-agent-task] WakeupNotify messages dropped on shutdown", telemetry.local);
68105
- }
68106
- async function startWakeupNotifyPull(opts) {
68107
- const enabled = opts.enabled ?? true;
68108
- const fetchPage = opts.fetchPage ?? (enabled ? createOnchainosWakeupFetchPage() : void 0);
68109
- if (!enabled || !fetchPage) {
68110
- logWithTimestamp("[okx-agent-task] WakeupNotify pull skipped (disabled)");
68111
- return null;
68112
- }
68113
- const agentIds = [
68114
- ...new Set(
68115
- [...opts.service.getClients().keys()].map((addr) => opts.service.getAgentByAddress(addr)?.agentId).filter((id) => typeof id === "string" && id.length > 0)
68116
- )
68117
- ];
68118
- if (agentIds.length === 0) {
68119
- logWithTimestamp("[okx-agent-task] WakeupNotify pull skipped (no active agents)");
68120
- return null;
68121
- }
68122
- logger.info(LogEvent.WAKEUP_PULL_STARTED, {
68123
- component: "wakeup_pull",
68124
- agentCount: String(agentIds.length)
68125
- });
68126
- const { items, summary, rejects } = await fetchAllWakeupNotifications({
68127
- agentIds,
68128
- fetchPage,
68129
- onPage: (p) => logger.info(LogEvent.WAKEUP_PULL_PAGE_FETCHED, {
68130
- component: "wakeup_pull",
68131
- page: String(p.page),
68132
- itemCount: String(p.itemCount),
68133
- rejectedCount: String(p.rejectedCount),
68134
- hasNextPage: String(p.hasNextPage)
68135
- }),
68136
- onRetry: (r) => logger.info(LogEvent.WAKEUP_PULL_PAGE_RETRY, {
68137
- component: "wakeup_pull",
68138
- page: String(r.page),
68139
- attempt: String(r.attempt),
68140
- reason: r.reason
68141
- })
68142
- });
68143
- for (const reject of rejects) {
68144
- logger.info(LogEvent.WAKEUP_NOTIFICATION_REJECTED, {
68145
- component: "wakeup_pull",
68146
- reason: reject.reason
68147
- });
68148
- }
68149
- if (summary.terminated === "transport_error" || summary.terminated === "business_error" || summary.terminated === "invalid_response") {
68150
- logger.error(LogEvent.WAKEUP_PULL_FAILED, void 0, {
68151
- component: "wakeup_pull",
68152
- terminated: summary.terminated
68153
- });
68154
- }
68155
- const resolved = opts.chunkSize != null ? { chunkSize: opts.chunkSize, anomaly: null } : resolveWakeupChunkSize(opts.env);
68156
- if (resolved.anomaly) {
68157
- logWithTimestamp(`[okx-agent-task] WakeupNotify chunk size ${resolved.anomaly}`);
68158
- }
68159
- const chunks = splitIntoChunks(items, resolved.chunkSize);
68160
- logger.info(LogEvent.WAKEUP_PULL_COMPLETED, {
68161
- component: "wakeup_pull",
68162
- pagesFetched: String(summary.pagesFetched),
68163
- received: String(summary.received),
68164
- rejected: String(summary.rejected),
68165
- chunkCount: String(chunks.length),
68166
- size: String(resolved.chunkSize),
68167
- terminated: summary.terminated
68168
- });
68169
- const deps = {
68170
- commands: opts.commands,
68171
- sessionStore: opts.sessionStore,
68172
- myXmtpAddress: void 0
68173
- };
68174
- const dispatcher = new HeartbeatChunkDispatcher(chunks, deps, opts.shouldContinue);
68175
- await dispatcher.dispatchNextChunk();
68176
- return dispatcher.hasPendingChunks() ? dispatcher : null;
68177
- }
68178
- var HeartbeatChunkDispatcher, MAX_LOGGED_PENDING_JOB_IDS;
68179
- var init_wakeup_pull = __esm({
68180
- "src/wakeup-pull.ts"() {
68181
- "use strict";
68182
- init_log();
68183
- init_sentry_logger();
68184
- init_wakeup_notify_ingest();
68185
- init_wakeup_notify_client();
68186
- init_wakeup_notify_transport();
68187
- init_wakeup_chunk_config();
68188
- HeartbeatChunkDispatcher = class {
68189
- constructor(chunks, deps, shouldContinue) {
68190
- this.chunks = chunks;
68191
- this.deps = deps;
68192
- this.shouldContinue = shouldContinue;
68193
- }
68194
- chunks;
68195
- deps;
68196
- shouldContinue;
68197
- index = 0;
68198
- /** True while a chunk is mid-dispatch (between taking it and its enqueues settling). */
68199
- dispatching = false;
68200
- hasPendingChunks() {
68201
- return this.index < this.chunks.length;
68202
- }
68203
- remainingChunks() {
68204
- return Math.max(0, this.chunks.length - this.index);
68205
- }
68206
- /**
68207
- * Read-only view of the not-yet-started chunks (for shutdown telemetry). `index` has
68208
- * already advanced past any in-flight chunk, so `chunks.slice(index)` is exactly the work
68209
- * that has not begun dispatching — the in-flight chunk is excluded from the dropped counts
68210
- * and reflected only by `inFlightChunk`.
68211
- */
68212
- pendingSnapshot() {
68213
- const notStarted = this.chunks.slice(this.index);
68214
- let droppedMessages = 0;
68215
- const jobIds = /* @__PURE__ */ new Set();
68216
- for (const chunk of notStarted) {
68217
- for (const item of chunk) {
68218
- droppedMessages += 1;
68219
- const jobId = item.message.jobId;
68220
- if (typeof jobId === "string" && jobId.length > 0) {
68221
- jobIds.add(jobId);
68222
- }
68223
- }
68224
- }
68225
- return {
68226
- remainingChunks: notStarted.length,
68227
- droppedMessages,
68228
- pendingJobIds: [...jobIds],
68229
- inFlightChunk: this.dispatching
68230
- };
68231
- }
68232
- /** Dispatch the next chunk: enqueue every message in it in parallel. No-op when drained. */
68233
- async dispatchNextChunk() {
68234
- if (this.shouldContinue && !this.shouldContinue()) {
68235
- return;
68236
- }
68237
- if (this.index >= this.chunks.length) {
68238
- return;
68239
- }
68240
- const chunk = this.chunks[this.index];
68241
- this.index += 1;
68242
- const chunkNumber = this.index;
68243
- this.dispatching = true;
68244
- let persisted = 0;
68245
- let partial = 0;
68246
- let rejected = 0;
68247
- try {
68248
- const outcomes = await Promise.allSettled(
68249
- chunk.map((item) => ingestWakeupNotification(item, this.deps))
68250
- );
68251
- for (const outcome of outcomes) {
68252
- if (outcome.status === "fulfilled") {
68253
- if (outcome.value.status === "persisted") {
68254
- persisted += 1;
68255
- } else if (outcome.value.status === "partial") {
68256
- partial += 1;
68257
- } else {
68258
- rejected += 1;
68259
- }
68260
- } else {
68261
- rejected += 1;
68262
- }
68263
- }
68264
- } finally {
68265
- this.dispatching = false;
68266
- }
68267
- logger.info(LogEvent.WAKEUP_CHUNK_DISPATCHED, {
68268
- component: "wakeup_pull",
68269
- chunk: String(chunkNumber),
68270
- chunkCount: String(this.chunks.length),
68271
- size: String(chunk.length),
68272
- persisted: String(persisted),
68273
- partial: String(partial),
68274
- rejected: String(rejected)
68275
- });
68276
- }
68277
- };
68278
- MAX_LOGGED_PENDING_JOB_IDS = 100;
68279
- }
68280
- });
68281
-
68282
67742
  // src/user-attention-watchers.ts
68283
67743
  function createUserAttentionWatchParentMonitor(options = {}) {
68284
67744
  const parentPid = options.parentPid ?? process.ppid;
@@ -68317,7 +67777,7 @@ function isOriginalParentProcessAlive(options) {
68317
67777
  }
68318
67778
  function registerUserAttentionWatcher(options) {
68319
67779
  return options.store.registerUserAttentionWatcher({
68320
- id: options.id ?? (0, import_node_crypto16.randomUUID)(),
67780
+ id: options.id ?? (0, import_node_crypto15.randomUUID)(),
68321
67781
  provider: options.provider,
68322
67782
  jobId: options.jobId,
68323
67783
  nowMs: options.nowMs ?? Date.now(),
@@ -68396,11 +67856,11 @@ function userWatchEventDeliveredSentryExtra(event) {
68396
67856
  hasDecision: String(event.hasDecision)
68397
67857
  };
68398
67858
  }
68399
- var import_node_crypto16, USER_ATTENTION_WATCH_REPLACED_MESSAGE, USER_ATTENTION_WATCHER_SCAN_MS, USER_ATTENTION_WATCHER_TTL_MS, USER_ATTENTION_WATCH_PARENT_CHECK_MS;
67859
+ var import_node_crypto15, USER_ATTENTION_WATCH_REPLACED_MESSAGE, USER_ATTENTION_WATCHER_SCAN_MS, USER_ATTENTION_WATCHER_TTL_MS, USER_ATTENTION_WATCH_PARENT_CHECK_MS;
68400
67860
  var init_user_attention_watchers = __esm({
68401
67861
  "src/user-attention-watchers.ts"() {
68402
67862
  "use strict";
68403
- import_node_crypto16 = require("node:crypto");
67863
+ import_node_crypto15 = require("node:crypto");
68404
67864
  init_sentry_logger();
68405
67865
  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.";
68406
67866
  USER_ATTENTION_WATCHER_SCAN_MS = 500;
@@ -68658,6 +68118,7 @@ async function runListenerWithLock(options, paths) {
68658
68118
  fetchSystemConfig: async () => fetchSystemConfig({
68659
68119
  notifySessionExpired: (command) => service.tools.notifySessionExpired?.(command)
68660
68120
  }),
68121
+ notifyAgentsWakeup: async (agentIds) => notifyAgentsWakeup(agentIds),
68661
68122
  createSigner: (agent) => createOnchainosSigner(agent),
68662
68123
  createInboundMiddleware: (deps) => createMiddlewareFromCoreDeps(store, deps, {
68663
68124
  sessionStore,
@@ -68707,12 +68168,12 @@ async function runListenerWithLock(options, paths) {
68707
68168
  });
68708
68169
  }
68709
68170
  });
68710
- service.setPluginVersion("0.2.9-beta-912b775358-260824171011");
68171
+ service.setPluginVersion("0.2.9");
68711
68172
  await service.init();
68712
68173
  const pluginVersionStatus = service.pluginVersionStatus;
68713
68174
  if (pluginVersionStatus.unavailable) {
68714
68175
  throw new Error(
68715
- `@okxweb3/a2a-node v${"0.2.9-beta-912b775358-260824171011"} is below the required minimum v${pluginVersionStatus.minVersion}`
68176
+ `@okxweb3/a2a-node v${"0.2.9"} is below the required minimum v${pluginVersionStatus.minVersion}`
68716
68177
  );
68717
68178
  }
68718
68179
  const systemConfig = service.getSystemConfig();
@@ -68740,7 +68201,7 @@ async function runListenerWithLock(options, paths) {
68740
68201
  onchainosAgentId: "*",
68741
68202
  reason: "system-config missing sentryDsn",
68742
68203
  pluginId: "@okxweb3/a2a-node",
68743
- pluginVersion: "0.2.9-beta-912b775358-260824171011"
68204
+ pluginVersion: "0.2.9"
68744
68205
  });
68745
68206
  }
68746
68207
  logWithTimestamp(
@@ -68983,7 +68444,6 @@ async function runListenerWithLock(options, paths) {
68983
68444
  let intervalSec = Math.max(10, service.getSystemConfig().heartbeatInterval);
68984
68445
  let offlineReplayIntervalSec = resolveOfflineReplayIntervalSec(service.getSystemConfig());
68985
68446
  let xmtpClientRecycleIntervalSec = resolveXmtpClientRecycleIntervalSec(service.getSystemConfig());
68986
- let wakeupDispatcher = null;
68987
68447
  let timer;
68988
68448
  let offlineReplayTimer;
68989
68449
  let xmtpClientRecycleTimer;
@@ -69002,7 +68462,6 @@ async function runListenerWithLock(options, paths) {
69002
68462
  versionRefresh: refreshOnchainosVersionMetadata,
69003
68463
  refresh: syncTick
69004
68464
  });
69005
- void wakeupDispatcher?.dispatchNextChunk();
69006
68465
  }, intervalSec * 1e3);
69007
68466
  };
69008
68467
  const scheduleOfflineReplayTimer = (nextIntervalSec) => {
@@ -69117,22 +68576,6 @@ async function runListenerWithLock(options, paths) {
69117
68576
  });
69118
68577
  await markDaemonReady(paths.daemonLockPath);
69119
68578
  logWithTimestamp(`[okx-agent-task] daemon ready lock=${paths.daemonLockPath}`);
69120
- void startWakeupNotifyPull({
69121
- service,
69122
- commands,
69123
- sessionStore,
69124
- // Stop enqueuing if a shutdown begins mid-delivery (fire-and-forget pull).
69125
- shouldContinue: () => !stopping
69126
- }).then((dispatcher) => {
69127
- wakeupDispatcher = dispatcher;
69128
- }).catch((err2) => {
69129
- logger.error(LogEvent.WAKEUP_PULL_FAILED, err2 instanceof Error ? err2 : new Error(String(err2)), {
69130
- component: "node_listener",
69131
- stage: "wakeup_pull_start",
69132
- reason: "wakeup_pull_unhandled_error"
69133
- });
69134
- logWithTimestamp("[okx-agent-task] WakeupNotify pull failed to start:", err2);
69135
- });
69136
68579
  await new Promise((resolve14) => {
69137
68580
  const shutdown2 = (signal) => {
69138
68581
  if (stopping) {
@@ -69145,7 +68588,6 @@ async function runListenerWithLock(options, paths) {
69145
68588
  resolve14();
69146
68589
  }, SHUTDOWN_FORCE_RESOLVE_MS);
69147
68590
  void (async () => {
69148
- logDroppedWakeupWorkOnShutdown(wakeupDispatcher);
69149
68591
  deferredMaintenanceTasks.cancelAll();
69150
68592
  if (timer) {
69151
68593
  clearInterval(timer);
@@ -69207,7 +68649,6 @@ var init_listener = __esm({
69207
68649
  init_file_store();
69208
68650
  init_session_store();
69209
68651
  init_command_processor();
69210
- init_wakeup_pull();
69211
68652
  init_command_store();
69212
68653
  init_ai_dispatch_queue();
69213
68654
  init_message_handler();
@@ -87471,7 +86912,7 @@ var require_fetch_pb = __commonJS({
87471
86912
  }
87472
86913
  });
87473
86914
  }
87474
- function isPlainObject6(value) {
86915
+ function isPlainObject4(value) {
87475
86916
  const isObject = Object.prototype.toString.call(value).slice(8, -1) === "Object";
87476
86917
  const isObjLike = value !== null && isObject;
87477
86918
  if (!isObjLike || !isObject) {
@@ -87494,7 +86935,7 @@ var require_fetch_pb = __commonJS({
87494
86935
  const isNonEmptyPrimitiveArray = Array.isArray(value) && value.every((v) => isPrimitive(v)) && value.length > 0;
87495
86936
  const isNonZeroValuePrimitive = isPrimitive(value) && !isZeroValuePrimitive(value);
87496
86937
  let objectToMerge = {};
87497
- if (isPlainObject6(value)) {
86938
+ if (isPlainObject4(value)) {
87498
86939
  objectToMerge = flattenRequestPayload(value, newPath);
87499
86940
  } else if (isNonZeroValuePrimitive || isNonEmptyPrimitiveArray) {
87500
86941
  objectToMerge = { [newPath]: value };
@@ -113063,10 +112504,10 @@ var require_node4 = __commonJS({
113063
112504
 
113064
112505
  // ../../node_modules/@xmtp/content-type-remote-attachment/dist/index.js
113065
112506
  async function encrypt(plain, secret, additionalData) {
113066
- const salt = import_node_crypto17.webcrypto.getRandomValues(new Uint8Array(KDFSaltSize));
113067
- const nonce = import_node_crypto17.webcrypto.getRandomValues(new Uint8Array(AESGCMNonceSize));
112507
+ const salt = import_node_crypto16.webcrypto.getRandomValues(new Uint8Array(KDFSaltSize));
112508
+ const nonce = import_node_crypto16.webcrypto.getRandomValues(new Uint8Array(AESGCMNonceSize));
113068
112509
  const key = await hkdf(secret, salt);
113069
- const encrypted = await import_node_crypto17.webcrypto.subtle.encrypt(aesGcmParams(nonce), key, plain);
112510
+ const encrypted = await import_node_crypto16.webcrypto.subtle.encrypt(aesGcmParams(nonce), key, plain);
113070
112511
  return new Ciphertext({
113071
112512
  aes256GcmHkdfSha256: {
113072
112513
  payload: new Uint8Array(encrypted),
@@ -113080,7 +112521,7 @@ async function decrypt(encrypted, secret, additionalData) {
113080
112521
  throw new Error("invalid payload ciphertext");
113081
112522
  }
113082
112523
  const key = await hkdf(secret, encrypted.aes256GcmHkdfSha256.hkdfSalt);
113083
- const decrypted = await import_node_crypto17.webcrypto.subtle.decrypt(aesGcmParams(encrypted.aes256GcmHkdfSha256.gcmNonce), key, encrypted.aes256GcmHkdfSha256.payload);
112524
+ const decrypted = await import_node_crypto16.webcrypto.subtle.decrypt(aesGcmParams(encrypted.aes256GcmHkdfSha256.gcmNonce), key, encrypted.aes256GcmHkdfSha256.payload);
113084
112525
  return new Uint8Array(decrypted);
113085
112526
  }
113086
112527
  function aesGcmParams(nonce, additionalData) {
@@ -113091,18 +112532,18 @@ function aesGcmParams(nonce, additionalData) {
113091
112532
  return spec;
113092
112533
  }
113093
112534
  async function hkdf(secret, salt) {
113094
- const key = await import_node_crypto17.webcrypto.subtle.importKey("raw", secret, "HKDF", false, [
112535
+ const key = await import_node_crypto16.webcrypto.subtle.importKey("raw", secret, "HKDF", false, [
113095
112536
  "deriveKey"
113096
112537
  ]);
113097
- return import_node_crypto17.webcrypto.subtle.deriveKey({ name: "HKDF", hash: "SHA-256", salt, info: hkdfNoInfo }, key, { name: "AES-GCM", length: 256 }, false, ["encrypt", "decrypt"]);
112538
+ return import_node_crypto16.webcrypto.subtle.deriveKey({ name: "HKDF", hash: "SHA-256", salt, info: hkdfNoInfo }, key, { name: "AES-GCM", length: 256 }, false, ["encrypt", "decrypt"]);
113098
112539
  }
113099
- var import_proto, import_node_crypto17, ContentTypeAttachment, AttachmentCodec, KDFSaltSize, AESGCMNonceSize, AESGCMTagLength, Ciphertext, hkdfNoInfo, ContentTypeRemoteAttachment, RemoteAttachmentCodec;
112540
+ var import_proto, import_node_crypto16, ContentTypeAttachment, AttachmentCodec, KDFSaltSize, AESGCMNonceSize, AESGCMTagLength, Ciphertext, hkdfNoInfo, ContentTypeRemoteAttachment, RemoteAttachmentCodec;
113100
112541
  var init_dist6 = __esm({
113101
112542
  "../../node_modules/@xmtp/content-type-remote-attachment/dist/index.js"() {
113102
112543
  init_dist5();
113103
112544
  init_secp256k12();
113104
112545
  import_proto = __toESM(require_node4(), 1);
113105
- import_node_crypto17 = require("node:crypto");
112546
+ import_node_crypto16 = require("node:crypto");
113106
112547
  ContentTypeAttachment = new ContentTypeId({
113107
112548
  authorityId: "xmtp.org",
113108
112549
  typeId: "attachment",
@@ -113182,7 +112623,7 @@ var init_dist6 = __esm({
113182
112623
  if (payload.length === 0) {
113183
112624
  throw new Error(`no payload for remote attachment at ${remoteAttachment.url}`);
113184
112625
  }
113185
- const digestBytes = new Uint8Array(await import_node_crypto17.webcrypto.subtle.digest("SHA-256", payload));
112626
+ const digestBytes = new Uint8Array(await import_node_crypto16.webcrypto.subtle.digest("SHA-256", payload));
113186
112627
  const digest = etc.bytesToHex(digestBytes);
113187
112628
  if (digest !== remoteAttachment.contentDigest) {
113188
112629
  throw new Error("content digest does not match");
@@ -113206,7 +112647,7 @@ var init_dist6 = __esm({
113206
112647
  return codec.decode(encodedContent, codecRegistry);
113207
112648
  }
113208
112649
  static async encodeEncrypted(content$1, codec) {
113209
- const secret = import_node_crypto17.webcrypto.getRandomValues(new Uint8Array(32));
112650
+ const secret = import_node_crypto16.webcrypto.getRandomValues(new Uint8Array(32));
113210
112651
  const encodedContent = import_proto.content.EncodedContent.encode(codec.encode(content$1, {
113211
112652
  codecFor() {
113212
112653
  return void 0;
@@ -113219,7 +112660,7 @@ var init_dist6 = __esm({
113219
112660
  if (!salt || !nonce || !payload) {
113220
112661
  throw new Error("missing encryption key");
113221
112662
  }
113222
- const digestBytes = new Uint8Array(await import_node_crypto17.webcrypto.subtle.digest("SHA-256", payload));
112663
+ const digestBytes = new Uint8Array(await import_node_crypto16.webcrypto.subtle.digest("SHA-256", payload));
113223
112664
  const digest = etc.bytesToHex(digestBytes);
113224
112665
  return {
113225
112666
  digest,
@@ -113437,7 +112878,7 @@ async function uploadFile(params) {
113437
112878
  const attachment = { filename, mimeType, data: new Uint8Array(data) };
113438
112879
  const encrypted = await RemoteAttachmentCodec.encodeEncrypted(attachment, new AttachmentCodec());
113439
112880
  ensureFileDirs();
113440
- const encryptedPath = (0, import_node_path33.resolve)(FILE_WORK_DIR, `${(0, import_node_crypto18.randomUUID)()}.enc`);
112881
+ const encryptedPath = (0, import_node_path33.resolve)(FILE_WORK_DIR, `${(0, import_node_crypto17.randomUUID)()}.enc`);
113441
112882
  (0, import_node_fs27.writeFileSync)(encryptedPath, encrypted.payload);
113442
112883
  try {
113443
112884
  const stdout = runOnchainos([
@@ -113481,7 +112922,7 @@ async function uploadFile(params) {
113481
112922
  }
113482
112923
  async function downloadFile(params) {
113483
112924
  ensureFileDirs();
113484
- const encryptedPath = (0, import_node_path33.resolve)(FILE_WORK_DIR, `${(0, import_node_crypto18.randomUUID)()}.enc`);
112925
+ const encryptedPath = (0, import_node_path33.resolve)(FILE_WORK_DIR, `${(0, import_node_crypto17.randomUUID)()}.enc`);
113485
112926
  try {
113486
112927
  const stdout = runOnchainos([
113487
112928
  "agent",
@@ -113506,7 +112947,7 @@ async function downloadFile(params) {
113506
112947
  throw new Error(`file download failed: ${stdout}`);
113507
112948
  }
113508
112949
  const payload = new Uint8Array((0, import_node_fs27.readFileSync)(encryptedPath));
113509
- const digestBytes = new Uint8Array(await import_node_crypto18.webcrypto.subtle.digest("SHA-256", payload));
112950
+ const digestBytes = new Uint8Array(await import_node_crypto17.webcrypto.subtle.digest("SHA-256", payload));
113510
112951
  const actualDigest = Array.from(digestBytes).map((byte) => byte.toString(16).padStart(2, "0")).join("");
113511
112952
  if (actualDigest !== params.digest) {
113512
112953
  throw new Error(`file download digest verification failed: expected=${params.digest}, actual=${actualDigest}`);
@@ -113514,7 +112955,7 @@ async function downloadFile(params) {
113514
112955
  const decryptedBytes = await decryptAttachmentPayload(payload, params);
113515
112956
  const encodedContent = import_proto2.content.EncodedContent.decode(decryptedBytes);
113516
112957
  const attachment = new AttachmentCodec().decode(encodedContent);
113517
- const outputFilename = params.filename || attachment.filename || `${(0, import_node_crypto18.randomUUID)()}.bin`;
112958
+ const outputFilename = params.filename || attachment.filename || `${(0, import_node_crypto17.randomUUID)()}.bin`;
113518
112959
  const outputDir = DOWNLOADS_DIR;
113519
112960
  ensureA2aTaskDir(outputDir);
113520
112961
  const outputPath = (0, import_node_path33.resolve)(outputDir, (0, import_node_path33.basename)(outputFilename));
@@ -113531,15 +112972,15 @@ async function decryptAttachmentPayload(payload, params) {
113531
112972
  const secretBytes = new Uint8Array(Buffer.from(params.secret, "base64"));
113532
112973
  const saltBytes = new Uint8Array(Buffer.from(params.salt, "base64"));
113533
112974
  const nonceBytes = new Uint8Array(Buffer.from(params.nonce, "base64"));
113534
- const hkdfKey = await import_node_crypto18.webcrypto.subtle.importKey("raw", secretBytes, "HKDF", false, ["deriveKey"]);
113535
- const aesKey = await import_node_crypto18.webcrypto.subtle.deriveKey(
112975
+ const hkdfKey = await import_node_crypto17.webcrypto.subtle.importKey("raw", secretBytes, "HKDF", false, ["deriveKey"]);
112976
+ const aesKey = await import_node_crypto17.webcrypto.subtle.deriveKey(
113536
112977
  { name: "HKDF", hash: "SHA-256", salt: saltBytes, info: new Uint8Array().buffer },
113537
112978
  hkdfKey,
113538
112979
  { name: "AES-GCM", length: 256 },
113539
112980
  false,
113540
112981
  ["decrypt"]
113541
112982
  );
113542
- return new Uint8Array(await import_node_crypto18.webcrypto.subtle.decrypt({ name: "AES-GCM", iv: nonceBytes }, aesKey, toArrayBuffer(payload)));
112983
+ return new Uint8Array(await import_node_crypto17.webcrypto.subtle.decrypt({ name: "AES-GCM", iv: nonceBytes }, aesKey, toArrayBuffer(payload)));
113543
112984
  }
113544
112985
  function toArrayBuffer(bytes) {
113545
112986
  return bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength);
@@ -113679,12 +113120,12 @@ function readRequiredOption(args, name) {
113679
113120
  }
113680
113121
  return value;
113681
113122
  }
113682
- var import_node_crypto18, import_node_fs27, import_node_path33, import_proto2, OKX_A2A_PATHS, OKX_A2A_HOME_DIR, FILE_WORK_DIR, DOWNLOADS_DIR, SYSTEM_CONFIG_PATH;
113123
+ var import_node_crypto17, import_node_fs27, import_node_path33, import_proto2, OKX_A2A_PATHS, OKX_A2A_HOME_DIR, FILE_WORK_DIR, DOWNLOADS_DIR, SYSTEM_CONFIG_PATH;
113683
113124
  var init_file_cli = __esm({
113684
113125
  "src/file-cli.ts"() {
113685
113126
  "use strict";
113686
113127
  init_win_spawn();
113687
- import_node_crypto18 = require("node:crypto");
113128
+ import_node_crypto17 = require("node:crypto");
113688
113129
  import_node_fs27 = require("node:fs");
113689
113130
  import_node_path33 = require("node:path");
113690
113131
  init_dist6();
@@ -117167,7 +116608,7 @@ async function getCurrentNodeCliVersion() {
117167
116608
  return await getGlobalNpmPackageVersion(UPDATE_PACKAGES.node) ?? getBundledNodeCliVersion();
117168
116609
  }
117169
116610
  function getBundledNodeCliVersion() {
117170
- return true ? "0.2.9-beta-912b775358-260824171011" : null;
116611
+ return true ? "0.2.9" : null;
117171
116612
  }
117172
116613
  function readConfiguredAiProvider() {
117173
116614
  const explicit = process.env.OKX_A2A_AI_PROVIDER || process.env.OKX_AGENT_TASK_AI_CLI;
@@ -117377,7 +116818,7 @@ async function updateHermes(release, options) {
117377
116818
  }
117378
116819
  }
117379
116820
  async function installGatewayPluginForDoctor(target) {
117380
- const release = isPrereleaseVersion("0.2.9-beta-912b775358-260824171011") ? "beta" : "latest";
116821
+ const release = isPrereleaseVersion("0.2.9") ? "beta" : "latest";
117381
116822
  const insideTargetGateway = detectGatewayInvocation() === target;
117382
116823
  const options = {
117383
116824
  restart: !insideTargetGateway,
@@ -118430,7 +117871,7 @@ async function runDoctor(options = {}) {
118430
117871
  platform: options.platform ?? process.platform,
118431
117872
  env: options.env ?? process.env,
118432
117873
  target: options.target ?? resolveDoctorTarget(options.env ?? process.env),
118433
- cliVersion: options.cliVersion ?? (true ? "0.2.9-beta-912b775358-260824171011" : "0.0.0"),
117874
+ cliVersion: options.cliVersion ?? (true ? "0.2.9" : "0.0.0"),
118434
117875
  fixMode: options.fix === true,
118435
117876
  nonInteractive: options.nonInteractive === true,
118436
117877
  packageChanged: false,
@@ -119458,7 +118899,7 @@ init_sentry_config();
119458
118899
  init_runtime_metadata();
119459
118900
  var CURRENT_GATEWAY_SESSION_KEYS_ENV4 = "OKX_A2A_CURRENT_GATEWAY_SESSION_KEYS";
119460
118901
  function printUsage3() {
119461
- console.log(`okx-a2a ${"0.2.9-beta-912b775358-260824171011"}
118902
+ console.log(`okx-a2a ${"0.2.9"}
119462
118903
 
119463
118904
  Usage:
119464
118905
  okx-a2a <command> [options]
@@ -119498,7 +118939,7 @@ Run \`okx-a2a <command> -h\` for command-specific help.
119498
118939
  `);
119499
118940
  }
119500
118941
  function printVersion() {
119501
- console.log("0.2.9-beta-912b775358-260824171011");
118942
+ console.log("0.2.9");
119502
118943
  }
119503
118944
  function printDaemonUsage() {
119504
118945
  console.log(`Usage: okx-a2a daemon <start|restart|stop|status|autostart> [options]
@@ -120979,7 +120420,7 @@ async function main() {
120979
120420
  if (command === "xmtp-test") {
120980
120421
  const { handleXmtpTestCommand: handleXmtpTestCommand2 } = await Promise.resolve().then(() => (init_xmtp_test_cli(), xmtp_test_cli_exports));
120981
120422
  await handleXmtpTestCommand2(process.argv.slice(3), {
120982
- packageVersion: "0.2.9-beta-912b775358-260824171011",
120423
+ packageVersion: "0.2.9",
120983
120424
  agentSdkVersion: "2.3.0",
120984
120425
  nodeSdkVersion: "6.1.0",
120985
120426
  nodeBindingsVersion: "1.11.0"