@okxweb3/a2a-node 0.2.7 → 0.2.8-beta-912b775358-260818171144

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 +807 -159
  2. package/dist/index.js +770 -139
  3. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -4492,7 +4492,7 @@ var require_is = __commonJS({
4492
4492
  function isPrimitive(wat) {
4493
4493
  return wat === null || typeof wat !== "object" && typeof wat !== "function";
4494
4494
  }
4495
- function isPlainObject4(wat) {
4495
+ function isPlainObject6(wat) {
4496
4496
  return isBuiltin(wat, "Object");
4497
4497
  }
4498
4498
  function isEvent(wat) {
@@ -4508,7 +4508,7 @@ var require_is = __commonJS({
4508
4508
  return Boolean(wat && wat.then && typeof wat.then === "function");
4509
4509
  }
4510
4510
  function isSyntheticEvent(wat) {
4511
- return isPlainObject4(wat) && "nativeEvent" in wat && "preventDefault" in wat && "stopPropagation" in wat;
4511
+ return isPlainObject6(wat) && "nativeEvent" in wat && "preventDefault" in wat && "stopPropagation" in wat;
4512
4512
  }
4513
4513
  function isNaN2(wat) {
4514
4514
  return typeof wat === "number" && wat !== wat;
@@ -4531,7 +4531,7 @@ var require_is = __commonJS({
4531
4531
  exports2.isEvent = isEvent;
4532
4532
  exports2.isInstanceOf = isInstanceOf;
4533
4533
  exports2.isNaN = isNaN2;
4534
- exports2.isPlainObject = isPlainObject4;
4534
+ exports2.isPlainObject = isPlainObject6;
4535
4535
  exports2.isPrimitive = isPrimitive;
4536
4536
  exports2.isRegExp = isRegExp;
4537
4537
  exports2.isString = isString;
@@ -6339,10 +6339,10 @@ var require_path = __commonJS({
6339
6339
  function isAbsolute4(path2) {
6340
6340
  return path2.charAt(0) === "/";
6341
6341
  }
6342
- function join33(...args) {
6342
+ function join34(...args) {
6343
6343
  return normalizePath(args.join("/"));
6344
6344
  }
6345
- function dirname10(path2) {
6345
+ function dirname11(path2) {
6346
6346
  const result = splitPath(path2);
6347
6347
  const root = result[0];
6348
6348
  let dir = result[1];
@@ -6362,9 +6362,9 @@ var require_path = __commonJS({
6362
6362
  return f;
6363
6363
  }
6364
6364
  exports2.basename = basename10;
6365
- exports2.dirname = dirname10;
6365
+ exports2.dirname = dirname11;
6366
6366
  exports2.isAbsolute = isAbsolute4;
6367
- exports2.join = join33;
6367
+ exports2.join = join34;
6368
6368
  exports2.normalizePath = normalizePath;
6369
6369
  exports2.relative = relative;
6370
6370
  exports2.resolve = resolve14;
@@ -19783,6 +19783,15 @@ var init_events = __esm({
19783
19783
  SYSTEM_NOTIFICATION_ROUTED: "System notification routed",
19784
19784
  HERMES_SESSION_ROUTE_BINDING: "Hermes session route binding",
19785
19785
  DOCTOR_REPORT: "Doctor report",
19786
+ // Paginated WakeupNotify recovery (BL-011) + bounded AI concurrency telemetry.
19787
+ // All info-level events below must ALSO be listed in SENTRY_INFO_ALLOWLIST
19788
+ // (index.ts) or info() drops them silently.
19789
+ WAKEUP_PULL_STARTED: "WakeupNotify pull started",
19790
+ WAKEUP_PULL_PAGE_FETCHED: "WakeupNotify pull page fetched",
19791
+ WAKEUP_PULL_PAGE_RETRY: "WakeupNotify pull page retry",
19792
+ WAKEUP_PULL_COMPLETED: "WakeupNotify pull completed",
19793
+ WAKEUP_NOTIFICATION_REJECTED: "WakeupNotify notification rejected",
19794
+ AI_CONCURRENCY_SNAPSHOT: "AI concurrency snapshot",
19786
19795
  // ── error ─────────────────────────────────────────────────────
19787
19796
  XMTP_CONNECTION_FAILED: "XMTP connection failed",
19788
19797
  CONVERSATIONS_STREAM_FAILED: "conversations.stream failed",
@@ -19837,6 +19846,7 @@ var init_events = __esm({
19837
19846
  AI_RUN_TOOL_FAILED: "AI run tool failed",
19838
19847
  IPC_FAILED: "IPC failed",
19839
19848
  NOTIFY_AGENTS_WAKEUP_FAILED: "Notify agents wakeup failed",
19849
+ WAKEUP_PULL_FAILED: "WakeupNotify pull failed",
19840
19850
  OUTBOUND_AGENT_LOOKUP_FAILED: "Outbound agent lookup failed",
19841
19851
  OUTBOUND_ELIGIBILITY_CHECK_FAILED: "Outbound eligibility check failed",
19842
19852
  OUTBOUND_ELIGIBILITY_BYPASSED: "Outbound eligibility bypassed",
@@ -20554,6 +20564,13 @@ var init_sentry_logger = __esm({
20554
20564
  LogEvent.USER_CHANNEL_MESSAGE_DELIVERED,
20555
20565
  LogEvent.SYSTEM_NOTIFICATION_RECEIVED,
20556
20566
  LogEvent.SYSTEM_NOTIFICATION_ROUTED,
20567
+ // Paginated WakeupNotify recovery (BL-011) + bounded AI concurrency telemetry.
20568
+ LogEvent.WAKEUP_PULL_STARTED,
20569
+ LogEvent.WAKEUP_PULL_PAGE_FETCHED,
20570
+ LogEvent.WAKEUP_PULL_PAGE_RETRY,
20571
+ LogEvent.WAKEUP_PULL_COMPLETED,
20572
+ LogEvent.WAKEUP_NOTIFICATION_REJECTED,
20573
+ LogEvent.AI_CONCURRENCY_SNAPSHOT,
20557
20574
  LogEvent.HERMES_SESSION_ROUTE_BINDING,
20558
20575
  LogEvent.INBOUND_BLOCKED_ADDRESS_MISMATCH,
20559
20576
  LogEvent.INBOUND_BLOCKED_INELIGIBLE,
@@ -24955,7 +24972,7 @@ var require_websocket2 = __commonJS({
24955
24972
  var http2 = require("http");
24956
24973
  var net = require("net");
24957
24974
  var tls = require("tls");
24958
- var { randomBytes: randomBytes4, createHash: createHash6 } = require("crypto");
24975
+ var { randomBytes: randomBytes4, createHash: createHash7 } = require("crypto");
24959
24976
  var { Duplex, Readable } = require("stream");
24960
24977
  var { URL: URL2 } = require("url");
24961
24978
  var PerMessageDeflate = require_permessage_deflate();
@@ -25615,7 +25632,7 @@ var require_websocket2 = __commonJS({
25615
25632
  abortHandshake(websocket, socket, "Invalid Upgrade header");
25616
25633
  return;
25617
25634
  }
25618
- const digest = createHash6("sha1").update(key + GUID).digest("base64");
25635
+ const digest = createHash7("sha1").update(key + GUID).digest("base64");
25619
25636
  if (res.headers["sec-websocket-accept"] !== digest) {
25620
25637
  abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
25621
25638
  return;
@@ -25982,7 +25999,7 @@ var require_websocket_server = __commonJS({
25982
25999
  var EventEmitter2 = require("events");
25983
26000
  var http2 = require("http");
25984
26001
  var { Duplex } = require("stream");
25985
- var { createHash: createHash6 } = require("crypto");
26002
+ var { createHash: createHash7 } = require("crypto");
25986
26003
  var extension = require_extension();
25987
26004
  var PerMessageDeflate = require_permessage_deflate();
25988
26005
  var subprotocol = require_subprotocol();
@@ -26283,7 +26300,7 @@ var require_websocket_server = __commonJS({
26283
26300
  );
26284
26301
  }
26285
26302
  if (this._state > RUNNING) return abortHandshake(socket, 503);
26286
- const digest = createHash6("sha1").update(key + GUID).digest("base64");
26303
+ const digest = createHash7("sha1").update(key + GUID).digest("base64");
26287
26304
  const headers = [
26288
26305
  "HTTP/1.1 101 Switching Protocols",
26289
26306
  "Upgrade: websocket",
@@ -26648,7 +26665,7 @@ function buildConnectParams(config, instanceId, protocolVersion) {
26648
26665
  client: {
26649
26666
  id: "gateway-client",
26650
26667
  displayName: "okx-a2a-node",
26651
- version: "0.2.7",
26668
+ version: "0.2.8-beta-912b775358-260818171144",
26652
26669
  platform: "node",
26653
26670
  mode: "backend",
26654
26671
  instanceId
@@ -26659,7 +26676,7 @@ function buildConnectParams(config, instanceId, protocolVersion) {
26659
26676
  commands: [],
26660
26677
  permissions: {},
26661
26678
  locale: Intl.DateTimeFormat().resolvedOptions().locale || "en-US",
26662
- userAgent: `okx-a2a-node/${"0.2.7"}`,
26679
+ userAgent: `okx-a2a-node/${"0.2.8-beta-912b775358-260818171144"}`,
26663
26680
  auth: {
26664
26681
  ...config.token ? { token: config.token } : {},
26665
26682
  ...config.password ? { password: config.password } : {}
@@ -28568,7 +28585,7 @@ var init_sentry_config = __esm({
28568
28585
  environment = process.env.SENTRY_ENV === "dev" ? "dev" : "prod";
28569
28586
  SENTRY_CONFIG = {
28570
28587
  projectName: "okx/openclaw-okx-a2a-extension",
28571
- release: "0.2.7",
28588
+ release: "0.2.8-beta-912b775358-260818171144",
28572
28589
  environment,
28573
28590
  runtimeContainer: normalizeRuntimeContainer(process.env.OKX_A2A_RUNTIME_CONTAINER)
28574
28591
  };
@@ -28857,7 +28874,7 @@ var require_BufferList = __commonJS({
28857
28874
  this.head = this.tail = null;
28858
28875
  this.length = 0;
28859
28876
  };
28860
- BufferList.prototype.join = function join33(s) {
28877
+ BufferList.prototype.join = function join34(s) {
28861
28878
  if (this.length === 0) return "";
28862
28879
  var p = this.head;
28863
28880
  var ret = "" + p.data;
@@ -39138,8 +39155,8 @@ function readSqliteRows(dbPath, sql, params = []) {
39138
39155
  if (!(0, import_node_fs17.existsSync)(dbPath)) {
39139
39156
  throw unavailable(`SQLite database not found: ${dbPath}`);
39140
39157
  }
39141
- const { DatabaseSync: DatabaseSync4 } = loadSqlite3();
39142
- const db = new DatabaseSync4(dbPath, { readOnly: true });
39158
+ const { DatabaseSync: DatabaseSync5 } = loadSqlite3();
39159
+ const db = new DatabaseSync5(dbPath, { readOnly: true });
39143
39160
  try {
39144
39161
  return db.prepare(sql).all(...params);
39145
39162
  } finally {
@@ -39738,7 +39755,7 @@ async function exportDiagnosticLogs(options) {
39738
39755
  node: process.version,
39739
39756
  platform: process.platform,
39740
39757
  arch: process.arch,
39741
- packageVersion: true ? "0.2.7" : "unknown",
39758
+ packageVersion: true ? "0.2.8-beta-912b775358-260818171144" : "unknown",
39742
39759
  sensitiveContentIncluded: options.includeSensitiveContent,
39743
39760
  listenerAndLlmContentIncluded: true,
39744
39761
  credentialsAlwaysRedacted: true,
@@ -58191,6 +58208,10 @@ var init_xmtp_sdk = __esm({
58191
58208
  timer
58192
58209
  });
58193
58210
  }
58211
+ // Public so the daemon (listener.ts) can invoke the legacy fire-and-forget wakeup
58212
+ // AFTER the command processor is ready, as one of two mutually-exclusive wakeup
58213
+ // paths (the other being the paginated WakeupNotify pull). It is intentionally no
58214
+ // longer called from completeStartupReplay — see the note there.
58194
58215
  notifyAgentsWakeupAfterReplay() {
58195
58216
  const notifyAgentsWakeup2 = this.tools.notifyAgentsWakeup;
58196
58217
  const agentIds = this.allAgents.map((agent) => agent.agentId);
@@ -58218,9 +58239,14 @@ var init_xmtp_sdk = __esm({
58218
58239
  /**
58219
58240
  * Completes the startup handoff from stored history to the live stream.
58220
58241
  * Listeners are already attached, but their host handlers stay buffered
58221
- * until replay finishes and the buffer is drained. Only then do we tell
58222
- * the backend that the agents are awake, so wakeup-triggered messages
58223
- * cannot overtake the stored backlog.
58242
+ * until replay finishes and the buffer is drained.
58243
+ *
58244
+ * Telling the backend the agents are awake is deliberately NOT done here.
58245
+ * The daemon (listener.ts) triggers exactly ONE wakeup path AFTER the bounded
58246
+ * command processor is ready — the paginated WakeupNotify pull when enabled, or
58247
+ * `notifyAgentsWakeupAfterReplay()` (the legacy fire-and-forget) otherwise — so
58248
+ * the two paths never overlap and wakeup-triggered work cannot be dispatched
58249
+ * before the processor exists.
58224
58250
  */
58225
58251
  async completeStartupReplay() {
58226
58252
  const startupGates = new Map(
@@ -58235,7 +58261,6 @@ var init_xmtp_sdk = __esm({
58235
58261
  }
58236
58262
  this.resolveStartupReplayCompletion?.();
58237
58263
  this.resolveStartupReplayCompletion = void 0;
58238
- this.notifyAgentsWakeupAfterReplay();
58239
58264
  return summary;
58240
58265
  }
58241
58266
  async startListeningForAddresses(addresses) {
@@ -64765,6 +64790,29 @@ var init_xmtp_debug = __esm({
64765
64790
  }
64766
64791
  });
64767
64792
 
64793
+ // src/ai-concurrency-config.ts
64794
+ function resolveMaxActiveAiExecutions(env = process.env) {
64795
+ const raw = env.OKX_A2A_MAX_ACTIVE_AI_EXECUTIONS ?? env.OKX_AGENT_TASK_MAX_ACTIVE_AI_EXECUTIONS;
64796
+ if (raw === void 0 || raw.trim() === "") {
64797
+ return { limit: DEFAULT_MAX_ACTIVE_AI_EXECUTIONS, anomaly: null };
64798
+ }
64799
+ const parsed = Number(raw);
64800
+ if (Number.isFinite(parsed) && Number.isInteger(parsed) && parsed > 0) {
64801
+ return { limit: parsed, anomaly: null };
64802
+ }
64803
+ return {
64804
+ limit: DEFAULT_MAX_ACTIVE_AI_EXECUTIONS,
64805
+ anomaly: `invalid value "${raw}", using default ${DEFAULT_MAX_ACTIVE_AI_EXECUTIONS}`
64806
+ };
64807
+ }
64808
+ var DEFAULT_MAX_ACTIVE_AI_EXECUTIONS;
64809
+ var init_ai_concurrency_config = __esm({
64810
+ "src/ai-concurrency-config.ts"() {
64811
+ "use strict";
64812
+ DEFAULT_MAX_ACTIVE_AI_EXECUTIONS = 4;
64813
+ }
64814
+ });
64815
+
64768
64816
  // src/command-processor.ts
64769
64817
  function commandSentryExtra(command, extra = {}) {
64770
64818
  const base = {
@@ -64814,6 +64862,17 @@ function startCommandProcessor(params) {
64814
64862
  const executionTimeoutMs = readPositiveEnv("OKX_A2A_COMMAND_EXECUTION_TIMEOUT_MS", DEFAULT_COMMAND_EXECUTION_TIMEOUT_MS);
64815
64863
  const staleTimeoutMs = readPositiveEnv("OKX_A2A_COMMAND_STALE_TIMEOUT_MS", DEFAULT_COMMAND_STALE_TIMEOUT_MS);
64816
64864
  const aiStaleTimeoutMs = readPositiveEnv("OKX_A2A_AI_COMMAND_STALE_TIMEOUT_MS", DEFAULT_AI_COMMAND_STALE_TIMEOUT_MS);
64865
+ const { limit: maxActiveAiExecutions, anomaly: aiLimitAnomaly } = resolveMaxActiveAiExecutions(process.env);
64866
+ if (aiLimitAnomaly) {
64867
+ logWithTimestamp(`[okx-agent-task] AI concurrency limit config anomaly: ${aiLimitAnomaly}`);
64868
+ logger.info(LogEvent.AI_CONCURRENCY_SNAPSHOT, {
64869
+ component: "node_command_processor",
64870
+ stage: "config",
64871
+ reason: "invalid_config_using_default",
64872
+ configuredLimit: String(maxActiveAiExecutions),
64873
+ anomaly: aiLimitAnomaly
64874
+ });
64875
+ }
64817
64876
  let inFlight = false;
64818
64877
  let aiScanInFlight = false;
64819
64878
  const activeAiQueueKeys = /* @__PURE__ */ new Set();
@@ -64903,6 +64962,9 @@ function startCommandProcessor(params) {
64903
64962
  inFlight = false;
64904
64963
  }
64905
64964
  };
64965
+ const AI_SNAPSHOT_MIN_INTERVAL_MS = 15e3;
64966
+ let lastAiSnapshotSignature = "";
64967
+ let lastAiSnapshotAtMs = 0;
64906
64968
  const aiTick = async () => {
64907
64969
  if (aiScanInFlight) {
64908
64970
  return;
@@ -64915,15 +64977,33 @@ function startCommandProcessor(params) {
64915
64977
  skipCommandIds: activeAiCommandIds
64916
64978
  });
64917
64979
  const pending = await commands.listPendingEntries();
64980
+ const pendingAi = pending.filter((entry) => isAiDispatchCommand(entry.command));
64981
+ if (activeAiCommandIds.size > 0 || pendingAi.length > 0) {
64982
+ const snapshotNow = Date.now();
64983
+ const oldestQueuedAgeMs = pendingAi.reduce((oldest, entry) => {
64984
+ const createdAt = Number.isFinite(entry.command.createdAt) ? entry.command.createdAt : entry.mtimeMs;
64985
+ return Math.max(oldest, snapshotNow - createdAt);
64986
+ }, 0);
64987
+ const snapshotSignature = `${maxActiveAiExecutions}|${activeAiCommandIds.size}|${pendingAi.length}`;
64988
+ if (snapshotSignature !== lastAiSnapshotSignature || snapshotNow - lastAiSnapshotAtMs >= AI_SNAPSHOT_MIN_INTERVAL_MS) {
64989
+ lastAiSnapshotSignature = snapshotSignature;
64990
+ lastAiSnapshotAtMs = snapshotNow;
64991
+ logger.info(LogEvent.AI_CONCURRENCY_SNAPSHOT, {
64992
+ component: "node_command_processor",
64993
+ configuredLimit: String(maxActiveAiExecutions),
64994
+ activeCount: String(activeAiCommandIds.size),
64995
+ queueDepth: String(pendingAi.length),
64996
+ oldestQueuedAgeMs: String(oldestQueuedAgeMs)
64997
+ });
64998
+ }
64999
+ } else {
65000
+ lastAiSnapshotSignature = "";
65001
+ }
64918
65002
  for (const entry of pending) {
64919
65003
  const command = entry.command;
64920
65004
  if (!isAiDispatchCommand(command)) {
64921
65005
  continue;
64922
65006
  }
64923
- const queueKey = buildAiCommandQueueKey(command);
64924
- if (activeAiQueueKeys.has(queueKey)) {
64925
- continue;
64926
- }
64927
65007
  if (isStalePending(entry, aiStaleTimeoutMs)) {
64928
65008
  const message = `${command.type}/${command.kind} command expired after ${formatDuration2(Date.now() - command.createdAt)} in pending queue`;
64929
65009
  await commands.completePending(command, {
@@ -64934,13 +65014,20 @@ function startCommandProcessor(params) {
64934
65014
  stage: "pending",
64935
65015
  ageMs: Date.now() - command.createdAt,
64936
65016
  timeoutMs: aiStaleTimeoutMs,
64937
- reason: "pending_expired"
65017
+ reason: "queue_expired"
64938
65018
  }));
64939
65019
  logWithTimestamp(
64940
65020
  `[okx-agent-task] ${command.type}/${command.kind} command expired id=${command.id}: ${message}`
64941
65021
  );
64942
65022
  continue;
64943
65023
  }
65024
+ if (activeAiCommandIds.size >= maxActiveAiExecutions) {
65025
+ continue;
65026
+ }
65027
+ const queueKey = buildAiCommandQueueKey(command);
65028
+ if (activeAiQueueKeys.has(queueKey)) {
65029
+ continue;
65030
+ }
64944
65031
  const processingPath = await commands.take(command);
64945
65032
  if (!processingPath) {
64946
65033
  continue;
@@ -65513,6 +65600,9 @@ function isStalePending(entry, staleTimeoutMs) {
65513
65600
  return Date.now() - createdAt > staleTimeoutMs;
65514
65601
  }
65515
65602
  function buildAiCommandQueueKey(command) {
65603
+ if (command.jobId) {
65604
+ return `job:${command.jobId}`;
65605
+ }
65516
65606
  if (command.kind === "job-message") {
65517
65607
  return buildDispatchSessionKey(command.jobId, command.sessionAgentId);
65518
65608
  }
@@ -65620,6 +65710,7 @@ var init_command_processor = __esm({
65620
65710
  init_user_attention_ipc();
65621
65711
  init_sentry_logger();
65622
65712
  init_xmtp_debug();
65713
+ init_ai_concurrency_config();
65623
65714
  DEFAULT_COMMAND_EXECUTION_TIMEOUT_MS = 5e4;
65624
65715
  DEFAULT_COMMAND_STALE_TIMEOUT_MS = 12e4;
65625
65716
  DEFAULT_AI_COMMAND_STALE_TIMEOUT_MS = 30 * 6e4;
@@ -65627,6 +65718,152 @@ var init_command_processor = __esm({
65627
65718
  }
65628
65719
  });
65629
65720
 
65721
+ // src/wakeup-notify-client.ts
65722
+ function isTransientTransportError(err2) {
65723
+ const message = err2 instanceof Error ? err2.message : String(err2);
65724
+ return TRANSIENT_TRANSPORT_PATTERN.test(message);
65725
+ }
65726
+ function isPlainObject3(value) {
65727
+ return !!value && typeof value === "object" && !Array.isArray(value);
65728
+ }
65729
+ function isValidWakeupItem(raw) {
65730
+ if (!isPlainObject3(raw)) {
65731
+ return { ok: false, reason: "malformed_item" };
65732
+ }
65733
+ if (typeof raw.agentId !== "string" || raw.agentId.length === 0) {
65734
+ return { ok: false, reason: "missing_agent_id" };
65735
+ }
65736
+ const message = raw.message;
65737
+ if (!isPlainObject3(message) || message.source !== "system") {
65738
+ return { ok: false, reason: "not_system_notification" };
65739
+ }
65740
+ if (message.event !== "wakeup_notify") {
65741
+ return { ok: false, reason: "not_wakeup_notify" };
65742
+ }
65743
+ return {
65744
+ ok: true,
65745
+ item: { agentId: raw.agentId, message }
65746
+ };
65747
+ }
65748
+ function canonicalize(value) {
65749
+ if (Array.isArray(value)) {
65750
+ return value.map(canonicalize);
65751
+ }
65752
+ if (value && typeof value === "object") {
65753
+ const source = value;
65754
+ return Object.keys(source).sort().reduce((acc, key) => {
65755
+ acc[key] = canonicalize(source[key]);
65756
+ return acc;
65757
+ }, {});
65758
+ }
65759
+ return value;
65760
+ }
65761
+ function deriveWakeupDedupeKey(item) {
65762
+ const canonicalMessage = JSON.stringify(canonicalize(item.message ?? {}));
65763
+ const identity = `${item.agentId}
65764
+ ${canonicalMessage}`;
65765
+ return `wakeup:${(0, import_node_crypto14.createHash)("sha256").update(identity).digest("hex").slice(0, 24)}`;
65766
+ }
65767
+ async function fetchAllWakeupNotifications(opts) {
65768
+ const { agentIds, fetchPage, onPage } = opts;
65769
+ const maxPages = opts.maxPages ?? DEFAULT_MAX_PAGES;
65770
+ const maxPageAttempts = opts.maxPageAttempts ?? DEFAULT_MAX_PAGE_ATTEMPTS;
65771
+ const retryDelayMs = opts.retryDelayMs ?? DEFAULT_PAGE_RETRY_DELAY_MS;
65772
+ const sleep5 = opts.sleep ?? ((ms) => new Promise((resolve14) => setTimeout(resolve14, ms)));
65773
+ const isRetryableError = opts.isRetryableError ?? isTransientTransportError;
65774
+ const onRetry = opts.onRetry;
65775
+ const fetchPageWithRetry = async (pageNum) => {
65776
+ let attempt = 0;
65777
+ while (true) {
65778
+ attempt++;
65779
+ try {
65780
+ return await fetchPage({ agentIds, page: pageNum });
65781
+ } catch (err2) {
65782
+ if (!isRetryableError(err2) || attempt >= maxPageAttempts) {
65783
+ throw err2;
65784
+ }
65785
+ onRetry?.({ page: pageNum, attempt, reason: "transient_transport" });
65786
+ await sleep5(retryDelayMs * attempt + Math.floor(Math.random() * (retryDelayMs + 1)));
65787
+ }
65788
+ }
65789
+ };
65790
+ const items = [];
65791
+ const rejects = [];
65792
+ const visited = /* @__PURE__ */ new Set();
65793
+ let pagesFetched = 0;
65794
+ let page = 1;
65795
+ let terminated = "empty";
65796
+ try {
65797
+ while (true) {
65798
+ const resp = await fetchPageWithRetry(page);
65799
+ pagesFetched++;
65800
+ if (resp.code !== 0) {
65801
+ terminated = "business_error";
65802
+ break;
65803
+ }
65804
+ const rawList = resp.data?.list;
65805
+ if (!Array.isArray(rawList)) {
65806
+ rejects.push({ reason: "invalid_response_list" });
65807
+ terminated = "invalid_response";
65808
+ break;
65809
+ }
65810
+ const list = rawList;
65811
+ let itemCount = 0;
65812
+ let rejectedCount = 0;
65813
+ for (const element of list) {
65814
+ const check = isValidWakeupItem(element);
65815
+ if (check.ok) {
65816
+ items.push(check.item);
65817
+ itemCount++;
65818
+ } else {
65819
+ rejects.push({ reason: check.reason });
65820
+ rejectedCount++;
65821
+ }
65822
+ }
65823
+ const nextPage = resp.data?.nextPage;
65824
+ onPage?.({ page, itemCount, rejectedCount, hasNextPage: nextPage != null });
65825
+ if (nextPage === null) {
65826
+ terminated = items.length || rejects.length ? "next_page_null" : "empty";
65827
+ break;
65828
+ }
65829
+ if (typeof nextPage !== "number" || !Number.isInteger(nextPage) || nextPage <= 0) {
65830
+ rejects.push({ reason: "invalid_next_page" });
65831
+ terminated = "invalid_response";
65832
+ break;
65833
+ }
65834
+ visited.add(page);
65835
+ page = nextPage;
65836
+ if (visited.has(page) || pagesFetched >= maxPages) {
65837
+ terminated = "max_pages";
65838
+ break;
65839
+ }
65840
+ }
65841
+ } catch {
65842
+ terminated = "transport_error";
65843
+ }
65844
+ const summary = {
65845
+ pagesFetched,
65846
+ received: items.length + rejects.length,
65847
+ persisted: 0,
65848
+ partial: 0,
65849
+ duplicates: 0,
65850
+ rejected: rejects.length,
65851
+ terminated
65852
+ };
65853
+ return { items, summary, rejects };
65854
+ }
65855
+ var import_node_crypto14, DEFAULT_MAX_PAGES, DEFAULT_MAX_PAGE_ATTEMPTS, DEFAULT_PAGE_RETRY_DELAY_MS, TRANSIENT_TRANSPORT_PATTERN;
65856
+ var init_wakeup_notify_client = __esm({
65857
+ "src/wakeup-notify-client.ts"() {
65858
+ "use strict";
65859
+ import_node_crypto14 = require("node:crypto");
65860
+ DEFAULT_MAX_PAGES = 200;
65861
+ DEFAULT_MAX_PAGE_ATTEMPTS = 3;
65862
+ DEFAULT_PAGE_RETRY_DELAY_MS = 500;
65863
+ TRANSIENT_TRANSPORT_PATTERN = /timed out|timeout|ETIMEDOUT|ECONNRESET|ECONNREFUSED|ENOTFOUND|EAI_AGAIN|socket hang up|network/i;
65864
+ }
65865
+ });
65866
+
65630
65867
  // src/ai-dispatch-queue.ts
65631
65868
  async function enqueueAiJobMessageDispatch(params) {
65632
65869
  const commands = params.commands ?? new CommandStore(params.homeDir);
@@ -65673,7 +65910,7 @@ function tryMarkProcessed(messageId) {
65673
65910
  }
65674
65911
  return true;
65675
65912
  }
65676
- function isPlainObject3(value) {
65913
+ function isPlainObject4(value) {
65677
65914
  return !!value && typeof value === "object" && !Array.isArray(value);
65678
65915
  }
65679
65916
  function safeStringify(value) {
@@ -65730,9 +65967,9 @@ function readNumber(value) {
65730
65967
  }
65731
65968
  function resolveSessionAgentId(params) {
65732
65969
  const { chatType, payload, myXmtpAddress } = params;
65733
- const payloadObject = isPlainObject3(payload) ? payload : null;
65734
- const sender = isPlainObject3(payloadObject?.sender) ? payloadObject.sender : null;
65735
- const message = isPlainObject3(payloadObject?.message) ? payloadObject.message : null;
65970
+ const payloadObject = isPlainObject4(payload) ? payload : null;
65971
+ const sender = isPlainObject4(payloadObject?.sender) ? payloadObject.sender : null;
65972
+ const message = isPlainObject4(payloadObject?.message) ? payloadObject.message : null;
65736
65973
  const localAgentId = XmtpService.getInstance().getAgentByAddress(myXmtpAddress)?.agentId ?? null;
65737
65974
  if (chatType === "group") {
65738
65975
  return readString5(sender?.agentId) ?? readString5(payloadObject?.receiverAgentId) ?? localAgentId;
@@ -65743,7 +65980,7 @@ function resolveSessionAgentId(params) {
65743
65980
  return localAgentId;
65744
65981
  }
65745
65982
  function routeMessage(chatType, parsed, payload) {
65746
- if (!parsed || !isPlainObject3(payload)) {
65983
+ if (!parsed || !isPlainObject4(payload)) {
65747
65984
  return {
65748
65985
  jobId: BACKUP_JOB_ID,
65749
65986
  route: "backup",
@@ -65755,7 +65992,7 @@ function routeMessage(chatType, parsed, payload) {
65755
65992
  return jobId ? { jobId, route: "job", routeReason: "group-job-id" } : { jobId: BACKUP_JOB_ID, route: "backup", routeReason: "group-missing-job-id" };
65756
65993
  }
65757
65994
  if (chatType === "dm") {
65758
- const message = isPlainObject3(payload.message) ? payload.message : null;
65995
+ const message = isPlainObject4(payload.message) ? payload.message : null;
65759
65996
  const nestedJobId = readString5(message?.jobId);
65760
65997
  const directJobId = readString5(payload.jobId);
65761
65998
  const jobId = nestedJobId ?? directJobId;
@@ -65768,10 +66005,10 @@ function routeMessage(chatType, parsed, payload) {
65768
66005
  return { jobId: BACKUP_JOB_ID, route: "backup", routeReason: "unknown-conversation" };
65769
66006
  }
65770
66007
  function extractDirectToUserNotification(payload) {
65771
- if (!isPlainObject3(payload)) {
66008
+ if (!isPlainObject4(payload)) {
65772
66009
  return { kind: "none" };
65773
66010
  }
65774
- const message = isPlainObject3(payload.message) ? payload.message : null;
66011
+ const message = isPlainObject4(payload.message) ? payload.message : null;
65775
66012
  if (message?.isDirectToUser !== true) {
65776
66013
  return { kind: "none" };
65777
66014
  }
@@ -65795,10 +66032,10 @@ function extractDirectToUserNotification(payload) {
65795
66032
  };
65796
66033
  }
65797
66034
  function extractSystemNotification(payload) {
65798
- if (!isPlainObject3(payload)) {
66035
+ if (!isPlainObject4(payload)) {
65799
66036
  return null;
65800
66037
  }
65801
- const message = isPlainObject3(payload.message) ? payload.message : null;
66038
+ const message = isPlainObject4(payload.message) ? payload.message : null;
65802
66039
  const isDirectCommunication = message?.isDirectCommunication === true;
65803
66040
  if (message?.source !== "system" && !isDirectCommunication) {
65804
66041
  return null;
@@ -66090,7 +66327,7 @@ function maybeNotifyInboundAgentMessage(params) {
66090
66327
  return;
66091
66328
  }
66092
66329
  const content2 = payloadObject.content;
66093
- const sender = isPlainObject3(payloadObject.sender) ? payloadObject.sender : null;
66330
+ const sender = isPlainObject4(payloadObject.sender) ? payloadObject.sender : null;
66094
66331
  const localAgent = XmtpService.getInstance().getAgentByAddress(params.deps.myXmtpAddress);
66095
66332
  void notifyAgentMessageToUserAttention({
66096
66333
  direction: "inbound" /* INBOUND */,
@@ -66121,11 +66358,11 @@ function stringifySystemPayload(payload) {
66121
66358
  }
66122
66359
  }
66123
66360
  function summarizePayloadForLog(payload) {
66124
- if (!isPlainObject3(payload)) {
66361
+ if (!isPlainObject4(payload)) {
66125
66362
  return "payload=non-object";
66126
66363
  }
66127
- const message = isPlainObject3(payload.message) ? payload.message : null;
66128
- const sender = isPlainObject3(payload.sender) ? payload.sender : null;
66364
+ const message = isPlainObject4(payload.message) ? payload.message : null;
66365
+ const sender = isPlainObject4(payload.sender) ? payload.sender : null;
66129
66366
  const jobId = readString5(payload.jobId) ?? readString5(message?.jobId);
66130
66367
  const parts = [
66131
66368
  readString5(payload.msgType) ? `type=${readString5(payload.msgType)}` : null,
@@ -66394,7 +66631,7 @@ async function verifyInboundA2AGroupMessage(params) {
66394
66631
  messageId,
66395
66632
  groupId,
66396
66633
  jobId,
66397
- agentId: readString5(isPlainObject3(payload.sender) ? payload.sender.agentId : null),
66634
+ agentId: readString5(isPlainObject4(payload.sender) ? payload.sender.agentId : null),
66398
66635
  localAgentId: myAgent?.agentId ?? null,
66399
66636
  senderAddress,
66400
66637
  senderInboxId,
@@ -66420,7 +66657,7 @@ async function verifyInboundA2AGroupMessage(params) {
66420
66657
  });
66421
66658
  return false;
66422
66659
  }
66423
- const sender = isPlainObject3(payload.sender) ? payload.sender : null;
66660
+ const sender = isPlainObject4(payload.sender) ? payload.sender : null;
66424
66661
  const senderAgentId = readString5(sender?.agentId);
66425
66662
  const senderRole = readNumber(sender?.role);
66426
66663
  if (!senderAgentId || !myAgent) {
@@ -66644,7 +66881,7 @@ async function processFileMessage(ctx, deps, options = {}) {
66644
66881
  timing.mark("payloadParse", parseStartedAt);
66645
66882
  const directToUser = chatType === "dm" && parseResult.ok ? extractDirectToUserNotification(parseResult.data) : { kind: "none" };
66646
66883
  if (directToUser.kind === "invalid") {
66647
- const droppedMessageId = messageId || `direct-to-user-${(0, import_node_crypto14.randomUUID)()}`;
66884
+ const droppedMessageId = messageId || `direct-to-user-${(0, import_node_crypto15.randomUUID)()}`;
66648
66885
  logger.error(
66649
66886
  LogEvent.INBOUND_DROP_DM_INVALID_PAYLOAD,
66650
66887
  new Error("Invalid direct-to-user system DM"),
@@ -66668,7 +66905,7 @@ async function processFileMessage(ctx, deps, options = {}) {
66668
66905
  await dispatchDirectToUserNotification({
66669
66906
  deps,
66670
66907
  notification: directToUser.notification,
66671
- messageId: messageId || `direct-to-user-${(0, import_node_crypto14.randomUUID)()}`,
66908
+ messageId: messageId || `direct-to-user-${(0, import_node_crypto15.randomUUID)()}`,
66672
66909
  timing,
66673
66910
  source: options.source ?? "live"
66674
66911
  });
@@ -66676,7 +66913,7 @@ async function processFileMessage(ctx, deps, options = {}) {
66676
66913
  }
66677
66914
  const systemNotification = chatType === "dm" && parseResult.ok ? extractSystemNotification(parseResult.data) : null;
66678
66915
  if (systemNotification) {
66679
- const systemMessageId = messageId || `system-${(0, import_node_crypto14.randomUUID)()}`;
66916
+ const systemMessageId = messageId || `system-${(0, import_node_crypto15.randomUUID)()}`;
66680
66917
  logWithTimestamp(
66681
66918
  `[okx-agent-task:${deps.myXmtpAddress}] xmtp_system_message_received agentId=${systemNotification.agentId ?? ""} msg=${shortenLogValue(systemMessageId)} event=${systemNotification.event ?? ""} job=${shortenLogValue(systemNotification.jobId)} conv=${conversationId} source=${options.source ?? "live"} rawBytes=${Buffer.byteLength(rawText, "utf8")} rawPreview=${previewRawEnvelope(rawText)}`
66682
66919
  );
@@ -66875,7 +67112,7 @@ async function processFileMessage(ctx, deps, options = {}) {
66875
67112
  );
66876
67113
  }
66877
67114
  if (route.route === "job" && chatType === "group") {
66878
- const payloadObject = isPlainObject3(parseResult.ok ? parseResult.data : null) ? parseResult.data : null;
67115
+ const payloadObject = isPlainObject4(parseResult.ok ? parseResult.data : null) ? parseResult.data : null;
66879
67116
  const service = XmtpService.getInstance();
66880
67117
  const trustedSystemSender = service.isTrustedSystemAccountSender({
66881
67118
  senderAddress,
@@ -66901,7 +67138,7 @@ async function processFileMessage(ctx, deps, options = {}) {
66901
67138
  });
66902
67139
  return true;
66903
67140
  }
66904
- const sender = isPlainObject3(payloadObject?.sender) ? payloadObject.sender : null;
67141
+ const sender = isPlainObject4(payloadObject?.sender) ? payloadObject.sender : null;
66905
67142
  const localAgent = service.getAgentByAddress(deps.myXmtpAddress);
66906
67143
  const myAgentId = localAgent?.agentId ?? readString5(payloadObject?.receiverAgentId) ?? sessionAgentId ?? null;
66907
67144
  const toAgentId = readString5(sender?.agentId);
@@ -66921,7 +67158,7 @@ async function processFileMessage(ctx, deps, options = {}) {
66921
67158
  if (!accepted) {
66922
67159
  return true;
66923
67160
  }
66924
- const routedMessageId = messageId || `group-${(0, import_node_crypto14.randomUUID)()}`;
67161
+ const routedMessageId = messageId || `group-${(0, import_node_crypto15.randomUUID)()}`;
66925
67162
  const sessionKey = ensureInboundGroupSession(deps, {
66926
67163
  jobId: route.jobId,
66927
67164
  myAgentId,
@@ -66987,7 +67224,7 @@ async function processFileMessage(ctx, deps, options = {}) {
66987
67224
  return true;
66988
67225
  }
66989
67226
  const stored = {
66990
- id: messageId || `local-${(0, import_node_crypto14.randomUUID)()}`,
67227
+ id: messageId || `local-${(0, import_node_crypto15.randomUUID)()}`,
66991
67228
  direction: "inbound",
66992
67229
  route: route.route,
66993
67230
  routeReason: route.routeReason,
@@ -67005,8 +67242,8 @@ async function processFileMessage(ctx, deps, options = {}) {
67005
67242
  await deps.store.append(route.jobId, stored, sessionAgentId);
67006
67243
  timing.mark("storeAppend", storeAppendStartedAt);
67007
67244
  if ((route.route === "job" || parseResult.ok && !isA2AEnvelope(stored.payload)) && !options.skipNotify) {
67008
- const payloadObject = isPlainObject3(stored.payload) ? stored.payload : null;
67009
- const sender = isPlainObject3(payloadObject?.sender) ? payloadObject.sender : null;
67245
+ const payloadObject = isPlainObject4(stored.payload) ? stored.payload : null;
67246
+ const sender = isPlainObject4(payloadObject?.sender) ? payloadObject.sender : null;
67010
67247
  const localAgent = XmtpService.getInstance().getAgentByAddress(deps.myXmtpAddress);
67011
67248
  const sessionKey = route.route === "job" ? buildSessionKey({
67012
67249
  jobId: route.jobId,
@@ -67024,8 +67261,8 @@ async function processFileMessage(ctx, deps, options = {}) {
67024
67261
  });
67025
67262
  }
67026
67263
  if (route.route === "job" && chatType === "group" && conversationId && senderAddress) {
67027
- const payloadObject = isPlainObject3(stored.payload) ? stored.payload : null;
67028
- const sender = isPlainObject3(payloadObject?.sender) ? payloadObject.sender : null;
67264
+ const payloadObject = isPlainObject4(stored.payload) ? stored.payload : null;
67265
+ const sender = isPlainObject4(payloadObject?.sender) ? payloadObject.sender : null;
67029
67266
  await deps.store.updateXmtpSession(route.jobId, {
67030
67267
  xmtpGroupId: conversationId,
67031
67268
  myXmtpAddress: deps.myXmtpAddress,
@@ -67168,7 +67405,7 @@ function processOfflineFromCoreDeps(store, ctx, deps, options) {
67168
67405
  function buildSystemStoredMessage(params) {
67169
67406
  const now = Date.now();
67170
67407
  return {
67171
- id: params.id ?? `system-${now}-${(0, import_node_crypto14.randomUUID)()}`,
67408
+ id: params.id ?? `system-${now}-${(0, import_node_crypto15.randomUUID)()}`,
67172
67409
  direction: "system",
67173
67410
  route: "backup",
67174
67411
  routeReason: params.reason,
@@ -67184,14 +67421,14 @@ function buildSystemStoredMessage(params) {
67184
67421
  };
67185
67422
  }
67186
67423
  function isA2AEnvelope(payload) {
67187
- return isPlainObject3(payload) && payload.msgType === A2A_MESSAGE_TYPE;
67424
+ return isPlainObject4(payload) && payload.msgType === A2A_MESSAGE_TYPE;
67188
67425
  }
67189
- var import_node_crypto14, PROCESSED_IDS_MAX, processedMessageIds, INBOUND_TRANSPORT, INBOUND_EVENT_FAMILY, INBOUND_TERMINAL_FIELDS;
67426
+ var import_node_crypto15, PROCESSED_IDS_MAX, processedMessageIds, INBOUND_TRANSPORT, INBOUND_EVENT_FAMILY, INBOUND_TERMINAL_FIELDS;
67190
67427
  var init_message_handler = __esm({
67191
67428
  "src/message-handler.ts"() {
67192
67429
  "use strict";
67193
67430
  init_log();
67194
- import_node_crypto14 = require("node:crypto");
67431
+ import_node_crypto15 = require("node:crypto");
67195
67432
  init_dist2();
67196
67433
  init_a2a();
67197
67434
  init_envelope_shared();
@@ -67220,6 +67457,396 @@ var init_message_handler = __esm({
67220
67457
  }
67221
67458
  });
67222
67459
 
67460
+ // src/wakeup-notify-ingest.ts
67461
+ async function ingestWakeupNotification(item, deps) {
67462
+ const dedupeKey = deriveWakeupDedupeKey(item);
67463
+ const itemJobId = item.message.jobId ?? null;
67464
+ if (deps.dedupe.has(dedupeKey)) {
67465
+ return { status: "duplicate", dedupeKey, jobId: itemJobId, targetCount: 0 };
67466
+ }
67467
+ const rawText = JSON.stringify({ agentId: item.agentId, message: item.message });
67468
+ const notif = extractSystemNotification(JSON.parse(rawText));
67469
+ if (!notif?.agentId) {
67470
+ return {
67471
+ status: "rejected",
67472
+ reason: "invalid_system_notification",
67473
+ dedupeKey,
67474
+ jobId: itemJobId,
67475
+ targetCount: 0
67476
+ };
67477
+ }
67478
+ const targets = resolveSystemNotificationTargets(
67479
+ { sessionStore: deps.sessionStore, myXmtpAddress: deps.myXmtpAddress ?? "", store: void 0 },
67480
+ notif
67481
+ );
67482
+ let succeeded = 0;
67483
+ let alreadyDelivered = 0;
67484
+ let failed = 0;
67485
+ for (const target of targets) {
67486
+ const targetKey = `${dedupeKey}:${target.sessionKey}`;
67487
+ if (deps.dedupe.has(targetKey)) {
67488
+ alreadyDelivered += 1;
67489
+ continue;
67490
+ }
67491
+ let enqueued = false;
67492
+ for (let attempt = 1; attempt <= MAX_TARGET_ENQUEUE_ATTEMPTS && !enqueued; attempt++) {
67493
+ try {
67494
+ await enqueueAiSessionMessageDispatch({
67495
+ commands: deps.commands,
67496
+ event: {
67497
+ sessionKey: target.sessionKey,
67498
+ content: rawText,
67499
+ // Stable messageId (= dedupeKey) avoids the `session-${Date.now()}`
67500
+ // intra-millisecond collision on rapid ingests.
67501
+ messageId: dedupeKey,
67502
+ jobId: target.jobId ?? null,
67503
+ agentId: target.agentId ?? null
67504
+ }
67505
+ });
67506
+ enqueued = true;
67507
+ } catch {
67508
+ }
67509
+ }
67510
+ if (enqueued) {
67511
+ try {
67512
+ deps.dedupe.recordIfNew(targetKey);
67513
+ } catch {
67514
+ }
67515
+ succeeded += 1;
67516
+ } else {
67517
+ failed += 1;
67518
+ }
67519
+ }
67520
+ const delivered = succeeded + alreadyDelivered;
67521
+ if (targets.length > 0 && delivered === 0) {
67522
+ return {
67523
+ status: "rejected",
67524
+ reason: "enqueue_failed",
67525
+ dedupeKey,
67526
+ jobId: notif.jobId ?? null,
67527
+ targetCount: 0,
67528
+ failedTargetCount: failed
67529
+ };
67530
+ }
67531
+ if (failed > 0) {
67532
+ return {
67533
+ status: "partial",
67534
+ reason: "partial_enqueue",
67535
+ dedupeKey,
67536
+ jobId: notif.jobId ?? null,
67537
+ targetCount: succeeded,
67538
+ failedTargetCount: failed
67539
+ };
67540
+ }
67541
+ if (delivered === targets.length) {
67542
+ try {
67543
+ deps.dedupe.recordIfNew(dedupeKey);
67544
+ } catch {
67545
+ }
67546
+ }
67547
+ return {
67548
+ status: "persisted",
67549
+ dedupeKey,
67550
+ jobId: notif.jobId ?? null,
67551
+ targetCount: succeeded
67552
+ };
67553
+ }
67554
+ var MAX_TARGET_ENQUEUE_ATTEMPTS;
67555
+ var init_wakeup_notify_ingest = __esm({
67556
+ "src/wakeup-notify-ingest.ts"() {
67557
+ "use strict";
67558
+ init_ai_dispatch_queue();
67559
+ init_message_handler();
67560
+ init_wakeup_notify_client();
67561
+ MAX_TARGET_ENQUEUE_ATTEMPTS = 3;
67562
+ }
67563
+ });
67564
+
67565
+ // src/wakeup-dedupe-store.ts
67566
+ function loadSqlite5() {
67567
+ const originalEmitWarning = process.emitWarning;
67568
+ process.emitWarning = ((warning, ...args) => {
67569
+ const message = typeof warning === "string" ? warning : warning.message;
67570
+ if (message.includes("SQLite is an experimental feature") && args.some((arg) => arg === "ExperimentalWarning")) {
67571
+ return;
67572
+ }
67573
+ return originalEmitWarning.call(process, warning, ...args);
67574
+ });
67575
+ try {
67576
+ return require("node:sqlite");
67577
+ } finally {
67578
+ process.emitWarning = originalEmitWarning;
67579
+ }
67580
+ }
67581
+ var import_node_path30, DatabaseSync4, WakeupDedupeStore;
67582
+ var init_wakeup_dedupe_store = __esm({
67583
+ "src/wakeup-dedupe-store.ts"() {
67584
+ "use strict";
67585
+ import_node_path30 = require("node:path");
67586
+ init_paths();
67587
+ ({ DatabaseSync: DatabaseSync4 } = loadSqlite5());
67588
+ WakeupDedupeStore = class {
67589
+ db;
67590
+ dbPath;
67591
+ constructor(homeDir) {
67592
+ this.dbPath = (0, import_node_path30.join)(resolveTaskPaths(homeDir).sqliteDir, "wakeup-dedupe.sqlite");
67593
+ ensureTaskDir((0, import_node_path30.dirname)(this.dbPath));
67594
+ this.db = new DatabaseSync4(this.dbPath);
67595
+ this.ensureReady();
67596
+ }
67597
+ /**
67598
+ * Atomically record the first sighting of `key`. Returns true when the row was
67599
+ * inserted (first sighting), false when it already existed (duplicate).
67600
+ */
67601
+ recordIfNew(key) {
67602
+ const result = this.db.prepare(`
67603
+ INSERT OR IGNORE INTO wakeup_ingest_dedupe (dedupe_key, first_seen_at_ms)
67604
+ VALUES (?, ?)
67605
+ `).run(key, Date.now());
67606
+ return Number(result.changes ?? 0) > 0;
67607
+ }
67608
+ /** Pre-check used before enqueue: has this key already been recorded? */
67609
+ has(key) {
67610
+ const row = this.db.prepare("SELECT 1 FROM wakeup_ingest_dedupe WHERE dedupe_key = ? LIMIT 1").get(key);
67611
+ return row !== void 0;
67612
+ }
67613
+ remove(key) {
67614
+ this.db.prepare("DELETE FROM wakeup_ingest_dedupe WHERE dedupe_key = ?").run(key);
67615
+ }
67616
+ close() {
67617
+ this.db.close();
67618
+ }
67619
+ ensureReady() {
67620
+ this.db.exec("PRAGMA busy_timeout=5000");
67621
+ this.db.exec("PRAGMA journal_mode=WAL");
67622
+ this.db.exec(`
67623
+ CREATE TABLE IF NOT EXISTS wakeup_ingest_dedupe (
67624
+ dedupe_key TEXT PRIMARY KEY,
67625
+ first_seen_at_ms INTEGER NOT NULL
67626
+ )
67627
+ `);
67628
+ }
67629
+ };
67630
+ }
67631
+ });
67632
+
67633
+ // src/wakeup-notify-transport.ts
67634
+ function withTimeout3(promise, timeoutMs, label) {
67635
+ return new Promise((resolve14, reject) => {
67636
+ const timer = setTimeout(() => {
67637
+ reject(new Error(`${label} timed out after ${timeoutMs}ms`));
67638
+ }, timeoutMs);
67639
+ promise.then(
67640
+ (value) => {
67641
+ clearTimeout(timer);
67642
+ resolve14(value);
67643
+ },
67644
+ (err2) => {
67645
+ clearTimeout(timer);
67646
+ reject(err2);
67647
+ }
67648
+ );
67649
+ });
67650
+ }
67651
+ function resolveCliTimeoutMs(override) {
67652
+ if (typeof override === "number" && Number.isFinite(override) && override > 0) {
67653
+ return override;
67654
+ }
67655
+ const raw = Number(process.env.OKX_A2A_WAKEUP_CLI_TIMEOUT_MS);
67656
+ return Number.isFinite(raw) && raw > 0 ? raw : DEFAULT_CLI_TIMEOUT_MS;
67657
+ }
67658
+ function isPlainObject5(value) {
67659
+ return !!value && typeof value === "object" && !Array.isArray(value);
67660
+ }
67661
+ function mapCliStdoutToWakeupResponse(parsed) {
67662
+ const root = isPlainObject5(parsed) ? parsed : {};
67663
+ const rootData = isPlainObject5(root.data) ? root.data : {};
67664
+ const nestedData = isPlainObject5(rootData.data) ? rootData.data : {};
67665
+ const candidates = [root, rootData, nestedData];
67666
+ let code;
67667
+ let msg;
67668
+ let list = [];
67669
+ let listFound = false;
67670
+ let nextPage = null;
67671
+ let nextPageFound = false;
67672
+ for (const candidate of candidates) {
67673
+ if (code === void 0 && typeof candidate.code === "number" && Number.isFinite(candidate.code)) {
67674
+ code = candidate.code;
67675
+ }
67676
+ if (msg === void 0 && typeof candidate.msg === "string") {
67677
+ msg = candidate.msg;
67678
+ }
67679
+ if (!listFound && Array.isArray(candidate.list)) {
67680
+ list = candidate.list;
67681
+ listFound = true;
67682
+ }
67683
+ if (!nextPageFound && "nextPage" in candidate) {
67684
+ const raw = candidate.nextPage;
67685
+ if (typeof raw === "number" && Number.isFinite(raw)) {
67686
+ nextPage = raw;
67687
+ nextPageFound = true;
67688
+ } else if (raw === null) {
67689
+ nextPage = null;
67690
+ nextPageFound = true;
67691
+ }
67692
+ }
67693
+ }
67694
+ if (code === void 0) {
67695
+ code = root.ok === true ? 0 : 1;
67696
+ }
67697
+ return {
67698
+ code,
67699
+ msg,
67700
+ data: { list: listFound ? list : void 0, nextPage: nextPageFound ? nextPage : void 0 }
67701
+ };
67702
+ }
67703
+ function createOnchainosWakeupFetchPage(deps = {}) {
67704
+ const timeoutMs = resolveCliTimeoutMs(deps.timeoutMs);
67705
+ const exec2 = deps.exec ?? ((args) => exec(args, { timeoutMs }));
67706
+ return async ({ agentIds, page }) => {
67707
+ const { stdout } = await withTimeout3(
67708
+ exec2([
67709
+ "agent",
67710
+ WAKEUP_NOTIFY_CLI_COMMAND,
67711
+ "--agent-ids",
67712
+ agentIds.join(","),
67713
+ // TBC: flag name/shape unconfirmed by backend/CLI.
67714
+ "--page",
67715
+ String(page)
67716
+ ]),
67717
+ timeoutMs,
67718
+ `onchainos ${WAKEUP_NOTIFY_CLI_COMMAND}`
67719
+ );
67720
+ const parsed = parseCliJson(stdout, WAKEUP_NOTIFY_CLI_COMMAND, {
67721
+ page: String(page)
67722
+ });
67723
+ return mapCliStdoutToWakeupResponse(parsed);
67724
+ };
67725
+ }
67726
+ var WAKEUP_NOTIFY_CLI_COMMAND, DEFAULT_CLI_TIMEOUT_MS;
67727
+ var init_wakeup_notify_transport = __esm({
67728
+ "src/wakeup-notify-transport.ts"() {
67729
+ "use strict";
67730
+ init_bin();
67731
+ init_cli_response();
67732
+ WAKEUP_NOTIFY_CLI_COMMAND = "wakeup-notify";
67733
+ DEFAULT_CLI_TIMEOUT_MS = 3e4;
67734
+ }
67735
+ });
67736
+
67737
+ // src/wakeup-recovery.ts
67738
+ async function startWakeupNotifyRecovery(opts) {
67739
+ const env = opts.env ?? process.env;
67740
+ const enabled = opts.enabled ?? env.OKX_A2A_WAKEUP_PULL_ENABLED === "1";
67741
+ const fetchPage = opts.fetchPage ?? (enabled ? createOnchainosWakeupFetchPage() : void 0);
67742
+ if (!enabled || !fetchPage) {
67743
+ logWithTimestamp(
67744
+ "[okx-agent-task] WakeupNotify pull skipped (disabled or transport not configured)"
67745
+ );
67746
+ return null;
67747
+ }
67748
+ const agentIds = [
67749
+ ...new Set(
67750
+ [...opts.service.getClients().keys()].map((addr) => opts.service.getAgentByAddress(addr)?.agentId).filter((id) => typeof id === "string" && id.length > 0)
67751
+ )
67752
+ ];
67753
+ if (agentIds.length === 0) {
67754
+ logWithTimestamp("[okx-agent-task] WakeupNotify pull skipped (no active agents)");
67755
+ return null;
67756
+ }
67757
+ logger.info(LogEvent.WAKEUP_PULL_STARTED, {
67758
+ component: "wakeup_recovery",
67759
+ agentCount: String(agentIds.length)
67760
+ });
67761
+ const dedupe = new WakeupDedupeStore(opts.homeDir);
67762
+ try {
67763
+ const { items, summary, rejects } = await fetchAllWakeupNotifications({
67764
+ agentIds,
67765
+ fetchPage,
67766
+ onPage: (p) => logger.info(LogEvent.WAKEUP_PULL_PAGE_FETCHED, {
67767
+ component: "wakeup_recovery",
67768
+ page: String(p.page),
67769
+ itemCount: String(p.itemCount),
67770
+ rejectedCount: String(p.rejectedCount),
67771
+ hasNextPage: String(p.hasNextPage)
67772
+ }),
67773
+ onRetry: (r) => logger.info(LogEvent.WAKEUP_PULL_PAGE_RETRY, {
67774
+ component: "wakeup_recovery",
67775
+ page: String(r.page),
67776
+ attempt: String(r.attempt),
67777
+ reason: r.reason
67778
+ })
67779
+ });
67780
+ for (const reject of rejects) {
67781
+ logger.info(LogEvent.WAKEUP_NOTIFICATION_REJECTED, {
67782
+ component: "wakeup_recovery",
67783
+ reason: reject.reason
67784
+ });
67785
+ }
67786
+ const shouldContinue = opts.shouldContinue;
67787
+ for (const item of items) {
67788
+ if (shouldContinue && !shouldContinue()) {
67789
+ logWithTimestamp("[okx-agent-task] WakeupNotify recovery halted early (daemon stopping)");
67790
+ break;
67791
+ }
67792
+ const outcome = await ingestWakeupNotification(item, {
67793
+ commands: opts.commands,
67794
+ sessionStore: opts.sessionStore,
67795
+ dedupe,
67796
+ myXmtpAddress: void 0
67797
+ });
67798
+ if (outcome.status === "persisted") {
67799
+ summary.persisted++;
67800
+ } else if (outcome.status === "partial") {
67801
+ summary.partial++;
67802
+ logger.info(LogEvent.WAKEUP_NOTIFICATION_REJECTED, {
67803
+ component: "wakeup_recovery",
67804
+ reason: outcome.reason ?? "partial_enqueue",
67805
+ failedTargetCount: String(outcome.failedTargetCount ?? 0)
67806
+ });
67807
+ } else if (outcome.status === "duplicate") {
67808
+ summary.duplicates++;
67809
+ } else {
67810
+ summary.rejected++;
67811
+ logger.info(LogEvent.WAKEUP_NOTIFICATION_REJECTED, {
67812
+ component: "wakeup_recovery",
67813
+ reason: outcome.reason ?? "unknown"
67814
+ });
67815
+ }
67816
+ }
67817
+ if (summary.terminated === "transport_error" || summary.terminated === "business_error" || summary.terminated === "invalid_response") {
67818
+ logger.error(LogEvent.WAKEUP_PULL_FAILED, void 0, {
67819
+ component: "wakeup_recovery",
67820
+ terminated: summary.terminated
67821
+ });
67822
+ }
67823
+ logger.info(LogEvent.WAKEUP_PULL_COMPLETED, {
67824
+ component: "wakeup_recovery",
67825
+ pagesFetched: String(summary.pagesFetched),
67826
+ received: String(summary.received),
67827
+ persisted: String(summary.persisted),
67828
+ partial: String(summary.partial),
67829
+ duplicates: String(summary.duplicates),
67830
+ rejected: String(summary.rejected),
67831
+ terminated: summary.terminated
67832
+ });
67833
+ return summary;
67834
+ } finally {
67835
+ dedupe.close();
67836
+ }
67837
+ }
67838
+ var init_wakeup_recovery = __esm({
67839
+ "src/wakeup-recovery.ts"() {
67840
+ "use strict";
67841
+ init_log();
67842
+ init_sentry_logger();
67843
+ init_wakeup_notify_client();
67844
+ init_wakeup_notify_ingest();
67845
+ init_wakeup_dedupe_store();
67846
+ init_wakeup_notify_transport();
67847
+ }
67848
+ });
67849
+
67223
67850
  // src/user-attention-watchers.ts
67224
67851
  function createUserAttentionWatchParentMonitor(options = {}) {
67225
67852
  const parentPid = options.parentPid ?? process.ppid;
@@ -67258,7 +67885,7 @@ function isOriginalParentProcessAlive(options) {
67258
67885
  }
67259
67886
  function registerUserAttentionWatcher(options) {
67260
67887
  return options.store.registerUserAttentionWatcher({
67261
- id: options.id ?? (0, import_node_crypto15.randomUUID)(),
67888
+ id: options.id ?? (0, import_node_crypto16.randomUUID)(),
67262
67889
  provider: options.provider,
67263
67890
  jobId: options.jobId,
67264
67891
  nowMs: options.nowMs ?? Date.now(),
@@ -67337,11 +67964,11 @@ function userWatchEventDeliveredSentryExtra(event) {
67337
67964
  hasDecision: String(event.hasDecision)
67338
67965
  };
67339
67966
  }
67340
- 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;
67967
+ 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;
67341
67968
  var init_user_attention_watchers = __esm({
67342
67969
  "src/user-attention-watchers.ts"() {
67343
67970
  "use strict";
67344
- import_node_crypto15 = require("node:crypto");
67971
+ import_node_crypto16 = require("node:crypto");
67345
67972
  init_sentry_logger();
67346
67973
  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.";
67347
67974
  USER_ATTENTION_WATCHER_SCAN_MS = 500;
@@ -67411,12 +68038,12 @@ async function isGatewayAvailableForHeartbeat(options) {
67411
68038
  }
67412
68039
  async function getHermesGatewayPluginStatus(options = {}) {
67413
68040
  const env = options.env ?? process.env;
67414
- const hermesHome = env.HERMES_HOME?.trim() || (0, import_node_path30.join)((0, import_node_os11.homedir)(), ".hermes");
67415
- const pluginYamlPath = (0, import_node_path30.join)(hermesHome, "plugins", "platforms", "okx-a2a", "plugin.yaml");
68041
+ const hermesHome = env.HERMES_HOME?.trim() || (0, import_node_path31.join)((0, import_node_os11.homedir)(), ".hermes");
68042
+ const pluginYamlPath = (0, import_node_path31.join)(hermesHome, "plugins", "platforms", "okx-a2a", "plugin.yaml");
67416
68043
  if (!(0, import_node_fs25.existsSync)(pluginYamlPath)) {
67417
68044
  return { enabled: false, reason: "plugin_yaml_missing", hermesHome, checkedPath: pluginYamlPath };
67418
68045
  }
67419
- const configPath = (0, import_node_path30.join)(hermesHome, "config.yaml");
68046
+ const configPath = (0, import_node_path31.join)(hermesHome, "config.yaml");
67420
68047
  let content2;
67421
68048
  try {
67422
68049
  content2 = await (0, import_promises13.readFile)(configPath, "utf8");
@@ -67648,12 +68275,12 @@ async function runListenerWithLock(options, paths) {
67648
68275
  });
67649
68276
  }
67650
68277
  });
67651
- service.setPluginVersion("0.2.7");
68278
+ service.setPluginVersion("0.2.8-beta-912b775358-260818171144");
67652
68279
  await service.init();
67653
68280
  const pluginVersionStatus = service.pluginVersionStatus;
67654
68281
  if (pluginVersionStatus.unavailable) {
67655
68282
  throw new Error(
67656
- `@okxweb3/a2a-node v${"0.2.7"} is below the required minimum v${pluginVersionStatus.minVersion}`
68283
+ `@okxweb3/a2a-node v${"0.2.8-beta-912b775358-260818171144"} is below the required minimum v${pluginVersionStatus.minVersion}`
67657
68284
  );
67658
68285
  }
67659
68286
  const systemConfig = service.getSystemConfig();
@@ -67671,7 +68298,7 @@ async function runListenerWithLock(options, paths) {
67671
68298
  onchainosAgentId: "*",
67672
68299
  reason: "system-config missing sentryDsn",
67673
68300
  pluginId: "@okxweb3/a2a-node",
67674
- pluginVersion: "0.2.7"
68301
+ pluginVersion: "0.2.8-beta-912b775358-260818171144"
67675
68302
  });
67676
68303
  }
67677
68304
  logWithTimestamp(
@@ -68044,6 +68671,26 @@ async function runListenerWithLock(options, paths) {
68044
68671
  });
68045
68672
  await markDaemonReady(paths.daemonLockPath);
68046
68673
  logWithTimestamp(`[okx-agent-task] daemon ready lock=${paths.daemonLockPath}`);
68674
+ if (process.env.OKX_A2A_WAKEUP_PULL_ENABLED === "1") {
68675
+ void startWakeupNotifyRecovery({
68676
+ service,
68677
+ commands,
68678
+ sessionStore,
68679
+ store,
68680
+ homeDir: options.homeDir,
68681
+ // Stop enqueuing if a shutdown begins mid-pull (fire-and-forget recovery).
68682
+ shouldContinue: () => !stopping
68683
+ }).catch((err2) => {
68684
+ logger.error(LogEvent.WAKEUP_PULL_FAILED, err2 instanceof Error ? err2 : new Error(String(err2)), {
68685
+ component: "node_listener",
68686
+ stage: "wakeup_recovery_start",
68687
+ reason: "wakeup_recovery_unhandled_error"
68688
+ });
68689
+ logWithTimestamp("[okx-agent-task] WakeupNotify recovery failed to start:", err2);
68690
+ });
68691
+ } else {
68692
+ service.notifyAgentsWakeupAfterReplay();
68693
+ }
68047
68694
  await new Promise((resolve14) => {
68048
68695
  const shutdown2 = (signal) => {
68049
68696
  if (stopping) {
@@ -68099,7 +68746,7 @@ async function timeSettled(fn) {
68099
68746
  return { durationMs: Date.now() - startedAt, error };
68100
68747
  }
68101
68748
  }
68102
- var import_node_fs25, import_promises13, import_node_os11, import_node_path30, DEFAULT_OFFLINE_REPLAY_INTERVAL_SEC, DEFAULT_XMTP_CLIENT_RECYCLE_INTERVAL_SEC, XMTP_CLIENT_RECYCLE_INTERVAL_ENV, HEARTBEAT_GATEWAY_CHECK_TIMEOUT_MS, AUTH_RECOVERY_PROBE_INTERVAL_MS, AUTH_RECOVERY_REFRESH_BACKOFF_MS, AgentRefreshAuthGate, AgentRefreshCoordinator, ListenerDeferredTaskScheduler, ListenerMaintenanceGate, UPGRADE_RECOMMENDATION_IDEMPOTENCY_KEY, SHUTDOWN_FORCE_RESOLVE_MS;
68749
+ var import_node_fs25, import_promises13, import_node_os11, import_node_path31, DEFAULT_OFFLINE_REPLAY_INTERVAL_SEC, DEFAULT_XMTP_CLIENT_RECYCLE_INTERVAL_SEC, XMTP_CLIENT_RECYCLE_INTERVAL_ENV, HEARTBEAT_GATEWAY_CHECK_TIMEOUT_MS, AUTH_RECOVERY_PROBE_INTERVAL_MS, AUTH_RECOVERY_REFRESH_BACKOFF_MS, AgentRefreshAuthGate, AgentRefreshCoordinator, ListenerDeferredTaskScheduler, ListenerMaintenanceGate, UPGRADE_RECOMMENDATION_IDEMPOTENCY_KEY, SHUTDOWN_FORCE_RESOLVE_MS;
68103
68750
  var init_listener = __esm({
68104
68751
  "src/listener.ts"() {
68105
68752
  "use strict";
@@ -68107,7 +68754,7 @@ var init_listener = __esm({
68107
68754
  import_node_fs25 = require("node:fs");
68108
68755
  import_promises13 = require("node:fs/promises");
68109
68756
  import_node_os11 = require("node:os");
68110
- import_node_path30 = require("node:path");
68757
+ import_node_path31 = require("node:path");
68111
68758
  init_onchainos();
68112
68759
  init_system_config();
68113
68760
  init_offline_replay_capability();
@@ -68116,6 +68763,7 @@ var init_listener = __esm({
68116
68763
  init_file_store();
68117
68764
  init_session_store();
68118
68765
  init_command_processor();
68766
+ init_wakeup_recovery();
68119
68767
  init_command_store();
68120
68768
  init_ai_dispatch_queue();
68121
68769
  init_message_handler();
@@ -68349,9 +68997,9 @@ async function handleXmtpTestCommand(args, releaseInfo) {
68349
68997
  async function startXmtpTest(args, releaseInfo) {
68350
68998
  assertKnownOptions(args, /* @__PURE__ */ new Set(["--name", "--run-id", "--json"]));
68351
68999
  const paths = resolveTaskPaths();
68352
- const testsDir = (0, import_node_path31.join)(paths.homeDir, "xmtp-tests");
69000
+ const testsDir = (0, import_node_path32.join)(paths.homeDir, "xmtp-tests");
68353
69001
  await ensurePrivateDir(testsDir);
68354
- const active = await readJsonIfExists((0, import_node_path31.join)(testsDir, ACTIVE_FILE));
69002
+ const active = await readJsonIfExists((0, import_node_path32.join)(testsDir, ACTIVE_FILE));
68355
69003
  if (active?.runId) {
68356
69004
  throw new Error(
68357
69005
  `XMTP test ${active.runId} is already active. Run \`okx-a2a xmtp-test stop\` first.`
@@ -68390,7 +69038,7 @@ async function startXmtpTest(args, releaseInfo) {
68390
69038
  ...releaseInfo
68391
69039
  };
68392
69040
  await writeJson(files.manifestPath, manifest);
68393
- await writeJson((0, import_node_path31.join)(testsDir, ACTIVE_FILE), {
69041
+ await writeJson((0, import_node_path32.join)(testsDir, ACTIVE_FILE), {
68394
69042
  runId,
68395
69043
  startedAt: manifest.startedAt
68396
69044
  });
@@ -68413,7 +69061,7 @@ Run \`okx-a2a xmtp-test watch\` to open the realtime dashboard.`);
68413
69061
  async function stopXmtpTest(args) {
68414
69062
  assertKnownOptions(args, /* @__PURE__ */ new Set(["--json"]));
68415
69063
  const testsDir = resolveTestsDir();
68416
- const activePath = (0, import_node_path31.join)(testsDir, ACTIVE_FILE);
69064
+ const activePath = (0, import_node_path32.join)(testsDir, ACTIVE_FILE);
68417
69065
  const active = await readJsonIfExists(activePath);
68418
69066
  if (!active?.runId) {
68419
69067
  throw new Error("No active XMTP test.");
@@ -68707,17 +69355,17 @@ function formatJobEvent(event) {
68707
69355
  return `${timestamp} ${businessEvent.padEnd(34)} ${role}#${agent} ${source}${timings.length > 0 ? ` ${timings.join(" ")}` : ""}`;
68708
69356
  }
68709
69357
  function resolveTestsDir() {
68710
- return (0, import_node_path31.join)(resolveTaskPaths().homeDir, "xmtp-tests");
69358
+ return (0, import_node_path32.join)(resolveTaskPaths().homeDir, "xmtp-tests");
68711
69359
  }
68712
69360
  function resolveRunFiles(testsDir, runId) {
68713
69361
  validateRunId(runId);
68714
- const runDir = (0, import_node_path31.join)(testsDir, runId);
69362
+ const runDir = (0, import_node_path32.join)(testsDir, runId);
68715
69363
  return {
68716
69364
  testsDir,
68717
69365
  runDir,
68718
- manifestPath: (0, import_node_path31.join)(runDir, "manifest.json"),
68719
- eventsPath: (0, import_node_path31.join)(runDir, "events.jsonl"),
68720
- summaryPath: (0, import_node_path31.join)(runDir, "summary.json")
69366
+ manifestPath: (0, import_node_path32.join)(runDir, "manifest.json"),
69367
+ eventsPath: (0, import_node_path32.join)(runDir, "events.jsonl"),
69368
+ summaryPath: (0, import_node_path32.join)(runDir, "summary.json")
68721
69369
  };
68722
69370
  }
68723
69371
  async function resolveRequestedRunId(testsDir, args, preferActive = false) {
@@ -68725,7 +69373,7 @@ async function resolveRequestedRunId(testsDir, args, preferActive = false) {
68725
69373
  if (requested) {
68726
69374
  return validateRunId(requested);
68727
69375
  }
68728
- const active = await readJsonIfExists((0, import_node_path31.join)(testsDir, ACTIVE_FILE));
69376
+ const active = await readJsonIfExists((0, import_node_path32.join)(testsDir, ACTIVE_FILE));
68729
69377
  if (active?.runId && (preferActive || !args.includes("--latest"))) {
68730
69378
  return validateRunId(active.runId);
68731
69379
  }
@@ -68751,7 +69399,7 @@ async function findLatestRunId(testsDir) {
68751
69399
  continue;
68752
69400
  }
68753
69401
  const manifest = await readJsonIfExists(
68754
- (0, import_node_path31.join)(testsDir, entry.name, "manifest.json")
69402
+ (0, import_node_path32.join)(testsDir, entry.name, "manifest.json")
68755
69403
  );
68756
69404
  if (manifest?.runId && manifest.startedAt) {
68757
69405
  manifests.push(manifest);
@@ -68986,12 +69634,12 @@ function formatPercent(value) {
68986
69634
  function validTimestamp(value) {
68987
69635
  return typeof value === "string" && Number.isFinite(Date.parse(value));
68988
69636
  }
68989
- var import_promises14, import_node_path31, RUN_ID_PATTERN2, ACTIVE_FILE;
69637
+ var import_promises14, import_node_path32, RUN_ID_PATTERN2, ACTIVE_FILE;
68990
69638
  var init_xmtp_test_cli = __esm({
68991
69639
  "src/xmtp-test-cli.ts"() {
68992
69640
  "use strict";
68993
69641
  import_promises14 = require("node:fs/promises");
68994
- import_node_path31 = require("node:path");
69642
+ import_node_path32 = require("node:path");
68995
69643
  init_daemon();
68996
69644
  init_log_tail();
68997
69645
  init_paths();
@@ -86377,7 +87025,7 @@ var require_fetch_pb = __commonJS({
86377
87025
  }
86378
87026
  });
86379
87027
  }
86380
- function isPlainObject4(value) {
87028
+ function isPlainObject6(value) {
86381
87029
  const isObject = Object.prototype.toString.call(value).slice(8, -1) === "Object";
86382
87030
  const isObjLike = value !== null && isObject;
86383
87031
  if (!isObjLike || !isObject) {
@@ -86400,7 +87048,7 @@ var require_fetch_pb = __commonJS({
86400
87048
  const isNonEmptyPrimitiveArray = Array.isArray(value) && value.every((v) => isPrimitive(v)) && value.length > 0;
86401
87049
  const isNonZeroValuePrimitive = isPrimitive(value) && !isZeroValuePrimitive(value);
86402
87050
  let objectToMerge = {};
86403
- if (isPlainObject4(value)) {
87051
+ if (isPlainObject6(value)) {
86404
87052
  objectToMerge = flattenRequestPayload(value, newPath);
86405
87053
  } else if (isNonZeroValuePrimitive || isNonEmptyPrimitiveArray) {
86406
87054
  objectToMerge = { [newPath]: value };
@@ -111969,10 +112617,10 @@ var require_node4 = __commonJS({
111969
112617
 
111970
112618
  // ../../node_modules/@xmtp/content-type-remote-attachment/dist/index.js
111971
112619
  async function encrypt(plain, secret, additionalData) {
111972
- const salt = import_node_crypto16.webcrypto.getRandomValues(new Uint8Array(KDFSaltSize));
111973
- const nonce = import_node_crypto16.webcrypto.getRandomValues(new Uint8Array(AESGCMNonceSize));
112620
+ const salt = import_node_crypto17.webcrypto.getRandomValues(new Uint8Array(KDFSaltSize));
112621
+ const nonce = import_node_crypto17.webcrypto.getRandomValues(new Uint8Array(AESGCMNonceSize));
111974
112622
  const key = await hkdf(secret, salt);
111975
- const encrypted = await import_node_crypto16.webcrypto.subtle.encrypt(aesGcmParams(nonce), key, plain);
112623
+ const encrypted = await import_node_crypto17.webcrypto.subtle.encrypt(aesGcmParams(nonce), key, plain);
111976
112624
  return new Ciphertext({
111977
112625
  aes256GcmHkdfSha256: {
111978
112626
  payload: new Uint8Array(encrypted),
@@ -111986,7 +112634,7 @@ async function decrypt(encrypted, secret, additionalData) {
111986
112634
  throw new Error("invalid payload ciphertext");
111987
112635
  }
111988
112636
  const key = await hkdf(secret, encrypted.aes256GcmHkdfSha256.hkdfSalt);
111989
- const decrypted = await import_node_crypto16.webcrypto.subtle.decrypt(aesGcmParams(encrypted.aes256GcmHkdfSha256.gcmNonce), key, encrypted.aes256GcmHkdfSha256.payload);
112637
+ const decrypted = await import_node_crypto17.webcrypto.subtle.decrypt(aesGcmParams(encrypted.aes256GcmHkdfSha256.gcmNonce), key, encrypted.aes256GcmHkdfSha256.payload);
111990
112638
  return new Uint8Array(decrypted);
111991
112639
  }
111992
112640
  function aesGcmParams(nonce, additionalData) {
@@ -111997,18 +112645,18 @@ function aesGcmParams(nonce, additionalData) {
111997
112645
  return spec;
111998
112646
  }
111999
112647
  async function hkdf(secret, salt) {
112000
- const key = await import_node_crypto16.webcrypto.subtle.importKey("raw", secret, "HKDF", false, [
112648
+ const key = await import_node_crypto17.webcrypto.subtle.importKey("raw", secret, "HKDF", false, [
112001
112649
  "deriveKey"
112002
112650
  ]);
112003
- return import_node_crypto16.webcrypto.subtle.deriveKey({ name: "HKDF", hash: "SHA-256", salt, info: hkdfNoInfo }, key, { name: "AES-GCM", length: 256 }, false, ["encrypt", "decrypt"]);
112651
+ return import_node_crypto17.webcrypto.subtle.deriveKey({ name: "HKDF", hash: "SHA-256", salt, info: hkdfNoInfo }, key, { name: "AES-GCM", length: 256 }, false, ["encrypt", "decrypt"]);
112004
112652
  }
112005
- var import_proto, import_node_crypto16, ContentTypeAttachment, AttachmentCodec, KDFSaltSize, AESGCMNonceSize, AESGCMTagLength, Ciphertext, hkdfNoInfo, ContentTypeRemoteAttachment, RemoteAttachmentCodec;
112653
+ var import_proto, import_node_crypto17, ContentTypeAttachment, AttachmentCodec, KDFSaltSize, AESGCMNonceSize, AESGCMTagLength, Ciphertext, hkdfNoInfo, ContentTypeRemoteAttachment, RemoteAttachmentCodec;
112006
112654
  var init_dist6 = __esm({
112007
112655
  "../../node_modules/@xmtp/content-type-remote-attachment/dist/index.js"() {
112008
112656
  init_dist5();
112009
112657
  init_secp256k12();
112010
112658
  import_proto = __toESM(require_node4(), 1);
112011
- import_node_crypto16 = require("node:crypto");
112659
+ import_node_crypto17 = require("node:crypto");
112012
112660
  ContentTypeAttachment = new ContentTypeId({
112013
112661
  authorityId: "xmtp.org",
112014
112662
  typeId: "attachment",
@@ -112088,7 +112736,7 @@ var init_dist6 = __esm({
112088
112736
  if (payload.length === 0) {
112089
112737
  throw new Error(`no payload for remote attachment at ${remoteAttachment.url}`);
112090
112738
  }
112091
- const digestBytes = new Uint8Array(await import_node_crypto16.webcrypto.subtle.digest("SHA-256", payload));
112739
+ const digestBytes = new Uint8Array(await import_node_crypto17.webcrypto.subtle.digest("SHA-256", payload));
112092
112740
  const digest = etc.bytesToHex(digestBytes);
112093
112741
  if (digest !== remoteAttachment.contentDigest) {
112094
112742
  throw new Error("content digest does not match");
@@ -112112,7 +112760,7 @@ var init_dist6 = __esm({
112112
112760
  return codec.decode(encodedContent, codecRegistry);
112113
112761
  }
112114
112762
  static async encodeEncrypted(content$1, codec) {
112115
- const secret = import_node_crypto16.webcrypto.getRandomValues(new Uint8Array(32));
112763
+ const secret = import_node_crypto17.webcrypto.getRandomValues(new Uint8Array(32));
112116
112764
  const encodedContent = import_proto.content.EncodedContent.encode(codec.encode(content$1, {
112117
112765
  codecFor() {
112118
112766
  return void 0;
@@ -112125,7 +112773,7 @@ var init_dist6 = __esm({
112125
112773
  if (!salt || !nonce || !payload) {
112126
112774
  throw new Error("missing encryption key");
112127
112775
  }
112128
- const digestBytes = new Uint8Array(await import_node_crypto16.webcrypto.subtle.digest("SHA-256", payload));
112776
+ const digestBytes = new Uint8Array(await import_node_crypto17.webcrypto.subtle.digest("SHA-256", payload));
112129
112777
  const digest = etc.bytesToHex(digestBytes);
112130
112778
  return {
112131
112779
  digest,
@@ -112180,9 +112828,9 @@ var init_dist6 = __esm({
112180
112828
 
112181
112829
  // ../core/src/file-upload-safety.ts
112182
112830
  function getUnsafeFileUploadReason(filePath, sensitiveUploadReg = []) {
112183
- const expanded = (0, import_node_path32.resolve)(expandHome(filePath));
112831
+ const expanded = (0, import_node_path33.resolve)(expandHome(filePath));
112184
112832
  const target = (0, import_node_fs26.realpathSync)(expanded);
112185
- const targetName = (0, import_node_path32.basename)(target);
112833
+ const targetName = (0, import_node_path33.basename)(target);
112186
112834
  if (targetName === ".env" || targetName.startsWith(".env.")) {
112187
112835
  return ".env";
112188
112836
  }
@@ -112195,13 +112843,13 @@ function getUnsafeFileUploadReason(filePath, sensitiveUploadReg = []) {
112195
112843
  return null;
112196
112844
  }
112197
112845
  for (const dir of SENSITIVE_HOME_DIRS) {
112198
- const sensitiveDir = safeRealpath((0, import_node_path32.join)(home, dir));
112846
+ const sensitiveDir = safeRealpath((0, import_node_path33.join)(home, dir));
112199
112847
  if (sensitiveDir && isPathInside(target, sensitiveDir)) {
112200
112848
  return `~/${dir}`;
112201
112849
  }
112202
112850
  }
112203
112851
  for (const file of SENSITIVE_HOME_FILES) {
112204
- const sensitiveFile = safeRealpath((0, import_node_path32.join)(home, file));
112852
+ const sensitiveFile = safeRealpath((0, import_node_path33.join)(home, file));
112205
112853
  if (sensitiveFile && target === sensitiveFile) {
112206
112854
  return `~/${file}`;
112207
112855
  }
@@ -112229,8 +112877,8 @@ function expandHome(filePath) {
112229
112877
  if (filePath === "~") {
112230
112878
  return (0, import_node_os12.homedir)();
112231
112879
  }
112232
- if (filePath.startsWith(`~${import_node_path32.sep}`)) {
112233
- return (0, import_node_path32.join)((0, import_node_os12.homedir)(), filePath.slice(2));
112880
+ if (filePath.startsWith(`~${import_node_path33.sep}`)) {
112881
+ return (0, import_node_path33.join)((0, import_node_os12.homedir)(), filePath.slice(2));
112234
112882
  }
112235
112883
  return filePath;
112236
112884
  }
@@ -112241,15 +112889,15 @@ function safeRealpath(path2) {
112241
112889
  return (0, import_node_fs26.realpathSync)(path2);
112242
112890
  }
112243
112891
  function isPathInside(target, dir) {
112244
- return target === dir || target.startsWith(`${dir}${import_node_path32.sep}`);
112892
+ return target === dir || target.startsWith(`${dir}${import_node_path33.sep}`);
112245
112893
  }
112246
- var import_node_fs26, import_node_os12, import_node_path32, SENSITIVE_HOME_DIRS, SENSITIVE_HOME_FILES, UNSAFE_FILE_UPLOAD_MESSAGE;
112894
+ var import_node_fs26, import_node_os12, import_node_path33, SENSITIVE_HOME_DIRS, SENSITIVE_HOME_FILES, UNSAFE_FILE_UPLOAD_MESSAGE;
112247
112895
  var init_file_upload_safety = __esm({
112248
112896
  "../core/src/file-upload-safety.ts"() {
112249
112897
  "use strict";
112250
112898
  import_node_fs26 = require("node:fs");
112251
112899
  import_node_os12 = require("node:os");
112252
- import_node_path32 = require("node:path");
112900
+ import_node_path33 = require("node:path");
112253
112901
  SENSITIVE_HOME_DIRS = [
112254
112902
  ".ssh",
112255
112903
  ".gnupg",
@@ -112257,7 +112905,7 @@ var init_file_upload_safety = __esm({
112257
112905
  ".azure",
112258
112906
  ".kube",
112259
112907
  ".docker",
112260
- (0, import_node_path32.join)(".config", "gcloud")
112908
+ (0, import_node_path33.join)(".config", "gcloud")
112261
112909
  ];
112262
112910
  SENSITIVE_HOME_FILES = [
112263
112911
  ".npmrc",
@@ -112319,7 +112967,7 @@ function hasHelpFlag(args) {
112319
112967
  return args.some((arg) => arg === "-h" || arg === "--help" || arg === "help");
112320
112968
  }
112321
112969
  async function uploadFile(params) {
112322
- const filename = params.filename || (0, import_node_path33.basename)(params.filePath);
112970
+ const filename = params.filename || (0, import_node_path34.basename)(params.filePath);
112323
112971
  const mimeType = params.mimeType || "application/octet-stream";
112324
112972
  const uploadConfig = readUploadSystemConfig();
112325
112973
  const unsafeReason = getUnsafeFileUploadReason(params.filePath, uploadConfig.sensitiveUploadReg);
@@ -112343,7 +112991,7 @@ async function uploadFile(params) {
112343
112991
  const attachment = { filename, mimeType, data: new Uint8Array(data) };
112344
112992
  const encrypted = await RemoteAttachmentCodec.encodeEncrypted(attachment, new AttachmentCodec());
112345
112993
  ensureFileDirs();
112346
- const encryptedPath = (0, import_node_path33.resolve)(FILE_WORK_DIR, `${(0, import_node_crypto17.randomUUID)()}.enc`);
112994
+ const encryptedPath = (0, import_node_path34.resolve)(FILE_WORK_DIR, `${(0, import_node_crypto18.randomUUID)()}.enc`);
112347
112995
  (0, import_node_fs27.writeFileSync)(encryptedPath, encrypted.payload);
112348
112996
  try {
112349
112997
  const stdout = runOnchainos([
@@ -112387,7 +113035,7 @@ async function uploadFile(params) {
112387
113035
  }
112388
113036
  async function downloadFile(params) {
112389
113037
  ensureFileDirs();
112390
- const encryptedPath = (0, import_node_path33.resolve)(FILE_WORK_DIR, `${(0, import_node_crypto17.randomUUID)()}.enc`);
113038
+ const encryptedPath = (0, import_node_path34.resolve)(FILE_WORK_DIR, `${(0, import_node_crypto18.randomUUID)()}.enc`);
112391
113039
  try {
112392
113040
  const stdout = runOnchainos([
112393
113041
  "agent",
@@ -112412,7 +113060,7 @@ async function downloadFile(params) {
112412
113060
  throw new Error(`file download failed: ${stdout}`);
112413
113061
  }
112414
113062
  const payload = new Uint8Array((0, import_node_fs27.readFileSync)(encryptedPath));
112415
- const digestBytes = new Uint8Array(await import_node_crypto17.webcrypto.subtle.digest("SHA-256", payload));
113063
+ const digestBytes = new Uint8Array(await import_node_crypto18.webcrypto.subtle.digest("SHA-256", payload));
112416
113064
  const actualDigest = Array.from(digestBytes).map((byte) => byte.toString(16).padStart(2, "0")).join("");
112417
113065
  if (actualDigest !== params.digest) {
112418
113066
  throw new Error(`file download digest verification failed: expected=${params.digest}, actual=${actualDigest}`);
@@ -112420,10 +113068,10 @@ async function downloadFile(params) {
112420
113068
  const decryptedBytes = await decryptAttachmentPayload(payload, params);
112421
113069
  const encodedContent = import_proto2.content.EncodedContent.decode(decryptedBytes);
112422
113070
  const attachment = new AttachmentCodec().decode(encodedContent);
112423
- const outputFilename = params.filename || attachment.filename || `${(0, import_node_crypto17.randomUUID)()}.bin`;
113071
+ const outputFilename = params.filename || attachment.filename || `${(0, import_node_crypto18.randomUUID)()}.bin`;
112424
113072
  const outputDir = DOWNLOADS_DIR;
112425
113073
  ensureA2aTaskDir(outputDir);
112426
- const outputPath = (0, import_node_path33.resolve)(outputDir, (0, import_node_path33.basename)(outputFilename));
113074
+ const outputPath = (0, import_node_path34.resolve)(outputDir, (0, import_node_path34.basename)(outputFilename));
112427
113075
  (0, import_node_fs27.writeFileSync)(outputPath, attachment.data);
112428
113076
  console.log(outputPath);
112429
113077
  } finally {
@@ -112437,15 +113085,15 @@ async function decryptAttachmentPayload(payload, params) {
112437
113085
  const secretBytes = new Uint8Array(Buffer.from(params.secret, "base64"));
112438
113086
  const saltBytes = new Uint8Array(Buffer.from(params.salt, "base64"));
112439
113087
  const nonceBytes = new Uint8Array(Buffer.from(params.nonce, "base64"));
112440
- const hkdfKey = await import_node_crypto17.webcrypto.subtle.importKey("raw", secretBytes, "HKDF", false, ["deriveKey"]);
112441
- const aesKey = await import_node_crypto17.webcrypto.subtle.deriveKey(
113088
+ const hkdfKey = await import_node_crypto18.webcrypto.subtle.importKey("raw", secretBytes, "HKDF", false, ["deriveKey"]);
113089
+ const aesKey = await import_node_crypto18.webcrypto.subtle.deriveKey(
112442
113090
  { name: "HKDF", hash: "SHA-256", salt: saltBytes, info: new Uint8Array().buffer },
112443
113091
  hkdfKey,
112444
113092
  { name: "AES-GCM", length: 256 },
112445
113093
  false,
112446
113094
  ["decrypt"]
112447
113095
  );
112448
- return new Uint8Array(await import_node_crypto17.webcrypto.subtle.decrypt({ name: "AES-GCM", iv: nonceBytes }, aesKey, toArrayBuffer(payload)));
113096
+ return new Uint8Array(await import_node_crypto18.webcrypto.subtle.decrypt({ name: "AES-GCM", iv: nonceBytes }, aesKey, toArrayBuffer(payload)));
112449
113097
  }
112450
113098
  function toArrayBuffer(bytes) {
112451
113099
  return bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength);
@@ -112585,14 +113233,14 @@ function readRequiredOption(args, name) {
112585
113233
  }
112586
113234
  return value;
112587
113235
  }
112588
- 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;
113236
+ var import_node_crypto18, import_node_fs27, import_node_path34, import_proto2, OKX_A2A_PATHS, OKX_A2A_HOME_DIR, FILE_WORK_DIR, DOWNLOADS_DIR, SYSTEM_CONFIG_PATH;
112589
113237
  var init_file_cli = __esm({
112590
113238
  "src/file-cli.ts"() {
112591
113239
  "use strict";
112592
113240
  init_win_spawn();
112593
- import_node_crypto17 = require("node:crypto");
113241
+ import_node_crypto18 = require("node:crypto");
112594
113242
  import_node_fs27 = require("node:fs");
112595
- import_node_path33 = require("node:path");
113243
+ import_node_path34 = require("node:path");
112596
113244
  init_dist6();
112597
113245
  import_proto2 = __toESM(require_node4());
112598
113246
  init_a2a_paths();
@@ -112603,7 +113251,7 @@ var init_file_cli = __esm({
112603
113251
  OKX_A2A_HOME_DIR = OKX_A2A_PATHS.homeDir;
112604
113252
  FILE_WORK_DIR = process.env.OKX_A2A_FILE_WORK_DIR || OKX_A2A_PATHS.filesDir;
112605
113253
  DOWNLOADS_DIR = process.env.OKX_A2A_DOWNLOADS_DIR || OKX_A2A_PATHS.downloadsDir;
112606
- SYSTEM_CONFIG_PATH = (0, import_node_path33.resolve)(OKX_A2A_PATHS.xmtpDir, "system-config.json");
113254
+ SYSTEM_CONFIG_PATH = (0, import_node_path34.resolve)(OKX_A2A_PATHS.xmtpDir, "system-config.json");
112607
113255
  }
112608
113256
  });
112609
113257
 
@@ -115243,13 +115891,13 @@ async function installWindowsNativeLauncher(options) {
115243
115891
  if (!(0, import_node_fs28.existsSync)(nodeExe)) {
115244
115892
  throw new Error(`cannot build okx-a2a.exe: node executable not found at ${nodeExe}`);
115245
115893
  }
115246
- const exePath = (0, import_node_path34.join)(options.targetDir, NATIVE_LAUNCHER_EXE_NAME);
115894
+ const exePath = (0, import_node_path35.join)(options.targetDir, NATIVE_LAUNCHER_EXE_NAME);
115247
115895
  (0, import_node_fs28.mkdirSync)(options.targetDir, { recursive: true });
115248
- const work = (0, import_node_fs28.mkdtempSync)((0, import_node_path34.join)((0, import_node_os13.tmpdir)(), "okx-a2a-sea-"));
115896
+ const work = (0, import_node_fs28.mkdtempSync)((0, import_node_path35.join)((0, import_node_os13.tmpdir)(), "okx-a2a-sea-"));
115249
115897
  try {
115250
- const entryPath = (0, import_node_path34.join)(work, "launcher-entry.js");
115251
- const blobPath = (0, import_node_path34.join)(work, "okx-a2a.blob");
115252
- const configPath = (0, import_node_path34.join)(work, "sea-config.json");
115898
+ const entryPath = (0, import_node_path35.join)(work, "launcher-entry.js");
115899
+ const blobPath = (0, import_node_path35.join)(work, "okx-a2a.blob");
115900
+ const configPath = (0, import_node_path35.join)(work, "sea-config.json");
115253
115901
  (0, import_node_fs28.writeFileSync)(entryPath, buildLauncherEntryJs(options.cliPath), "utf8");
115254
115902
  (0, import_node_fs28.writeFileSync)(configPath, buildSeaConfig(entryPath, blobPath), "utf8");
115255
115903
  (0, import_node_child_process9.execFileSync)(nodeExe, ["--experimental-sea-config", configPath], {
@@ -115282,13 +115930,13 @@ async function installWindowsNativeLauncher(options) {
115282
115930
  function findWindowsNativeOkxA2aExe(pathValue, appData, userProfile, fileExists2 = import_node_fs28.existsSync) {
115283
115931
  const dirs = pathValue.split(";").map((d) => d.trim()).filter(Boolean);
115284
115932
  if (appData) {
115285
- dirs.push((0, import_node_path34.join)(appData, "npm"));
115933
+ dirs.push((0, import_node_path35.join)(appData, "npm"));
115286
115934
  }
115287
115935
  if (userProfile) {
115288
- dirs.push((0, import_node_path34.join)(userProfile, ".local", "bin"));
115936
+ dirs.push((0, import_node_path35.join)(userProfile, ".local", "bin"));
115289
115937
  }
115290
115938
  for (const dir of dirs) {
115291
- const candidate = (0, import_node_path34.join)(dir, NATIVE_LAUNCHER_EXE_NAME);
115939
+ const candidate = (0, import_node_path35.join)(dir, NATIVE_LAUNCHER_EXE_NAME);
115292
115940
  if (fileExists2(candidate)) {
115293
115941
  return candidate;
115294
115942
  }
@@ -115300,7 +115948,7 @@ function resolveRunningCliPath() {
115300
115948
  if (fromArgv && /(?:^|[\\/])cli\.js$/.test(fromArgv) && (0, import_node_fs28.existsSync)(fromArgv)) {
115301
115949
  return fromArgv;
115302
115950
  }
115303
- const beside = (0, import_node_path34.join)(__dirname, "cli.js");
115951
+ const beside = (0, import_node_path35.join)(__dirname, "cli.js");
115304
115952
  if ((0, import_node_fs28.existsSync)(beside)) {
115305
115953
  return beside;
115306
115954
  }
@@ -115319,11 +115967,11 @@ async function ensureWindowsNativeLauncher(options = {}) {
115319
115967
  if (existing) {
115320
115968
  return { exePath: existing, installed: false };
115321
115969
  }
115322
- const targetDir = env.APPDATA ? (0, import_node_path34.join)(env.APPDATA, "npm") : (0, import_node_path34.join)(env.USERPROFILE ?? (0, import_node_os13.homedir)(), ".local", "bin");
115970
+ const targetDir = env.APPDATA ? (0, import_node_path35.join)(env.APPDATA, "npm") : (0, import_node_path35.join)(env.USERPROFILE ?? (0, import_node_os13.homedir)(), ".local", "bin");
115323
115971
  const result = await installWindowsNativeLauncher({ cliPath: resolveRunningCliPath(), targetDir });
115324
115972
  return { exePath: result.exePath, installed: true };
115325
115973
  }
115326
- var import_node_child_process9, import_node_fs28, import_node_module, import_node_os13, import_node_path34, SEA_SENTINEL_FUSE, NATIVE_LAUNCHER_EXE_NAME, POSTJECT_SPEC, POSTJECT_BIN;
115974
+ var import_node_child_process9, import_node_fs28, import_node_module, import_node_os13, import_node_path35, SEA_SENTINEL_FUSE, NATIVE_LAUNCHER_EXE_NAME, POSTJECT_SPEC, POSTJECT_BIN;
115327
115975
  var init_win_native_launcher = __esm({
115328
115976
  "src/win-native-launcher.ts"() {
115329
115977
  "use strict";
@@ -115331,7 +115979,7 @@ var init_win_native_launcher = __esm({
115331
115979
  import_node_fs28 = require("node:fs");
115332
115980
  import_node_module = require("node:module");
115333
115981
  import_node_os13 = require("node:os");
115334
- import_node_path34 = require("node:path");
115982
+ import_node_path35 = require("node:path");
115335
115983
  init_win_compat();
115336
115984
  init_win_spawn();
115337
115985
  SEA_SENTINEL_FUSE = "NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2";
@@ -116073,7 +116721,7 @@ async function getCurrentNodeCliVersion() {
116073
116721
  return await getGlobalNpmPackageVersion(UPDATE_PACKAGES.node) ?? getBundledNodeCliVersion();
116074
116722
  }
116075
116723
  function getBundledNodeCliVersion() {
116076
- return true ? "0.2.7" : null;
116724
+ return true ? "0.2.8-beta-912b775358-260818171144" : null;
116077
116725
  }
116078
116726
  function readConfiguredAiProvider() {
116079
116727
  const explicit = process.env.OKX_A2A_AI_PROVIDER || process.env.OKX_AGENT_TASK_AI_CLI;
@@ -116258,17 +116906,17 @@ async function updateHermes(release, options) {
116258
116906
  assertNotRunningInsideGateway("hermes");
116259
116907
  }
116260
116908
  const spec = buildNpmPackageSpec("hermes", release);
116261
- const workDir = await (0, import_promises15.mkdtemp)((0, import_node_path35.join)((0, import_node_os14.tmpdir)(), `okx-a2a-${label}-hermes-`));
116909
+ const workDir = await (0, import_promises15.mkdtemp)((0, import_node_path36.join)((0, import_node_os14.tmpdir)(), `okx-a2a-${label}-hermes-`));
116262
116910
  try {
116263
116911
  console.log(`[${label}] downloading ${spec}`);
116264
116912
  const npmTarball = await npmPack(spec, workDir);
116265
- const npmPackageDir = (0, import_node_path35.join)(workDir, "npm-package");
116913
+ const npmPackageDir = (0, import_node_path36.join)(workDir, "npm-package");
116266
116914
  await runCommand("tar", ["-xzf", npmTarball, "-C", npmPackageDir], { ensureDir: npmPackageDir });
116267
- const pluginTarball = await findHermesPluginTarball((0, import_node_path35.join)(npmPackageDir, "package", "dist"));
116268
- const pluginDir = (0, import_node_path35.join)(workDir, "plugin");
116915
+ const pluginTarball = await findHermesPluginTarball((0, import_node_path36.join)(npmPackageDir, "package", "dist"));
116916
+ const pluginDir = (0, import_node_path36.join)(workDir, "plugin");
116269
116917
  await runCommand("tar", ["-xzf", pluginTarball, "-C", pluginDir], { ensureDir: pluginDir });
116270
116918
  const unpackedPluginDir = await findFirstDirectory(pluginDir);
116271
- const installer = (0, import_node_path35.join)(unpackedPluginDir, "scripts", "install-or-upgrade.sh");
116919
+ const installer = (0, import_node_path36.join)(unpackedPluginDir, "scripts", "install-or-upgrade.sh");
116272
116920
  console.log(`[${label}] running ${installer}`);
116273
116921
  await runCommand("bash", [installer, ...options.restart ? ["--restart"] : []], { cwd: unpackedPluginDir });
116274
116922
  await normalizeHermesOkxA2aPluginConfig();
@@ -116283,7 +116931,7 @@ async function updateHermes(release, options) {
116283
116931
  }
116284
116932
  }
116285
116933
  async function installGatewayPluginForDoctor(target) {
116286
- const release = isPrereleaseVersion("0.2.7") ? "beta" : "latest";
116934
+ const release = isPrereleaseVersion("0.2.8-beta-912b775358-260818171144") ? "beta" : "latest";
116287
116935
  const insideTargetGateway = detectGatewayInvocation() === target;
116288
116936
  const options = {
116289
116937
  restart: !insideTargetGateway,
@@ -116334,7 +116982,7 @@ async function ensureHermesOkxA2aPluginConfig(configFile = resolveHermesConfigPa
116334
116982
  if (options.dryRun) {
116335
116983
  return true;
116336
116984
  }
116337
- await (0, import_promises15.mkdir)((0, import_node_path35.resolve)(configFile, ".."), { recursive: true });
116985
+ await (0, import_promises15.mkdir)((0, import_node_path36.resolve)(configFile, ".."), { recursive: true });
116338
116986
  await (0, import_promises15.writeFile)(configFile, "plugins:\n enabled:\n - okx-a2a\n");
116339
116987
  console.log(`[update] added Hermes plugins.enabled okx-a2a entry in ${configFile}`);
116340
116988
  return true;
@@ -116574,7 +117222,7 @@ function findFirstEnabledListItem(lines, startIndex, enabledIndent) {
116574
117222
  return null;
116575
117223
  }
116576
117224
  function resolveHermesConfigPath() {
116577
- return (0, import_node_path35.join)(process.env.HERMES_HOME ?? (0, import_node_path35.join)((0, import_node_os14.homedir)(), ".hermes"), "config.yaml");
117225
+ return (0, import_node_path36.join)(process.env.HERMES_HOME ?? (0, import_node_path36.join)((0, import_node_os14.homedir)(), ".hermes"), "config.yaml");
116578
117226
  }
116579
117227
  function lineIndent(line) {
116580
117228
  const match = line.match(/^\s*/);
@@ -116652,7 +117300,7 @@ async function assertGatewayPluginInstalled(target) {
116652
117300
  );
116653
117301
  }
116654
117302
  function resolveHermesPluginYamlPath() {
116655
- return (0, import_node_path35.join)(process.env.HERMES_HOME ?? (0, import_node_path35.join)((0, import_node_os14.homedir)(), ".hermes"), "plugins", "platforms", "okx-a2a", "plugin.yaml");
117303
+ return (0, import_node_path36.join)(process.env.HERMES_HOME ?? (0, import_node_path36.join)((0, import_node_os14.homedir)(), ".hermes"), "plugins", "platforms", "okx-a2a", "plugin.yaml");
116656
117304
  }
116657
117305
  async function isGatewayPluginInstalled(target) {
116658
117306
  if (target === "openclaw") {
@@ -116745,7 +117393,7 @@ function parsePackageVersionFromText(output5) {
116745
117393
  return output5.match(/@okxweb3\/a2a-openclaw@([0-9A-Za-z.+-]+)/)?.[1] ?? null;
116746
117394
  }
116747
117395
  async function getInstalledHermesPluginVersion() {
116748
- const pluginYaml = (0, import_node_path35.join)(process.env.HERMES_HOME ?? (0, import_node_path35.join)((0, import_node_os14.homedir)(), ".hermes"), "plugins", "platforms", "okx-a2a", "plugin.yaml");
117396
+ const pluginYaml = (0, import_node_path36.join)(process.env.HERMES_HOME ?? (0, import_node_path36.join)((0, import_node_os14.homedir)(), ".hermes"), "plugins", "platforms", "okx-a2a", "plugin.yaml");
116749
117397
  try {
116750
117398
  const content2 = await (0, import_promises15.readFile)(pluginYaml, "utf8");
116751
117399
  return parsePluginYamlVersion(content2);
@@ -116803,7 +117451,7 @@ async function npmPack(spec, destination) {
116803
117451
  if (!tarballName) {
116804
117452
  throw new Error(`Unable to detect npm pack tarball from output: ${output5.trim()}`);
116805
117453
  }
116806
- return (0, import_node_path35.resolve)(destination, (0, import_node_path35.basename)(tarballName));
117454
+ return (0, import_node_path36.resolve)(destination, (0, import_node_path36.basename)(tarballName));
116807
117455
  }
116808
117456
  async function findHermesPluginTarball(distDir) {
116809
117457
  const entries = await (0, import_promises15.readdir)(distDir);
@@ -116811,7 +117459,7 @@ async function findHermesPluginTarball(distDir) {
116811
117459
  if (!tarball) {
116812
117460
  throw new Error(`Hermes npm package did not contain dist/okx-a2a-hermes-plugin-*.tar.gz`);
116813
117461
  }
116814
- return (0, import_node_path35.join)(distDir, tarball);
117462
+ return (0, import_node_path36.join)(distDir, tarball);
116815
117463
  }
116816
117464
  async function findFirstDirectory(parent) {
116817
117465
  const entries = await (0, import_promises15.readdir)(parent, { withFileTypes: true });
@@ -116819,7 +117467,7 @@ async function findFirstDirectory(parent) {
116819
117467
  if (!dir) {
116820
117468
  throw new Error(`No unpacked plugin directory found under ${parent}`);
116821
117469
  }
116822
- return (0, import_node_path35.join)(parent, dir.name);
117470
+ return (0, import_node_path36.join)(parent, dir.name);
116823
117471
  }
116824
117472
  function readOption4(args, name) {
116825
117473
  const index2 = args.indexOf(name);
@@ -117040,7 +117688,7 @@ function buildExternalCommandInvocation(command, args, platform = process.platfo
117040
117688
  function formatExternalCommand(command, args) {
117041
117689
  return [command, ...args].join(" ");
117042
117690
  }
117043
- var import_node_child_process10, import_node_fs29, import_promises15, import_node_os14, import_node_path35, UPDATE_PACKAGES, CODEX_NPM_PACKAGE, OPENCLAW_FORCE_INSTALL_FLAG, OPENCLAW_UNSAFE_INSTALL_FLAG, OKX_A2A_PLUGIN_ID, OPENCLAW_SESSION_DM_SCOPE_CONFIG_PATH, OPENCLAW_SESSION_DM_SCOPE_CONFIG_VALUE, OPENCLAW_PLUGIN_ALLOW_CONFIG_PATH, OPENCLAW_OKX_A2A_CONVERSATION_HOOK_ACCESS_CONFIG_PATH, DEFAULT_AI_PROVIDER_LOGIN_TIMEOUT_MS, PROVIDER_CLI_AUTH_PROBE_TIMEOUT_MS, SetupBlockedError, redirectCommandStdoutToStderr;
117691
+ var import_node_child_process10, import_node_fs29, import_promises15, import_node_os14, import_node_path36, UPDATE_PACKAGES, CODEX_NPM_PACKAGE, OPENCLAW_FORCE_INSTALL_FLAG, OPENCLAW_UNSAFE_INSTALL_FLAG, OKX_A2A_PLUGIN_ID, OPENCLAW_SESSION_DM_SCOPE_CONFIG_PATH, OPENCLAW_SESSION_DM_SCOPE_CONFIG_VALUE, OPENCLAW_PLUGIN_ALLOW_CONFIG_PATH, OPENCLAW_OKX_A2A_CONVERSATION_HOOK_ACCESS_CONFIG_PATH, DEFAULT_AI_PROVIDER_LOGIN_TIMEOUT_MS, PROVIDER_CLI_AUTH_PROBE_TIMEOUT_MS, SetupBlockedError, redirectCommandStdoutToStderr;
117044
117692
  var init_update_cli = __esm({
117045
117693
  "src/update-cli.ts"() {
117046
117694
  "use strict";
@@ -117048,7 +117696,7 @@ var init_update_cli = __esm({
117048
117696
  import_node_fs29 = require("node:fs");
117049
117697
  import_promises15 = require("node:fs/promises");
117050
117698
  import_node_os14 = require("node:os");
117051
- import_node_path35 = require("node:path");
117699
+ import_node_path36 = require("node:path");
117052
117700
  init_ai_command();
117053
117701
  init_win_spawn();
117054
117702
  init_ai_provider();
@@ -117329,7 +117977,7 @@ async function runDoctor(options = {}) {
117329
117977
  platform: options.platform ?? process.platform,
117330
117978
  env: options.env ?? process.env,
117331
117979
  target: options.target ?? resolveDoctorTarget(options.env ?? process.env),
117332
- cliVersion: options.cliVersion ?? (true ? "0.2.7" : "0.0.0"),
117980
+ cliVersion: options.cliVersion ?? (true ? "0.2.8-beta-912b775358-260818171144" : "0.0.0"),
117333
117981
  fixMode: options.fix === true,
117334
117982
  nonInteractive: options.nonInteractive === true,
117335
117983
  packageChanged: false,
@@ -117537,11 +118185,11 @@ async function writeStdoutAndExit(output5, code) {
117537
118185
  });
117538
118186
  process.exit(code);
117539
118187
  }
117540
- var import_node_path36, DOCTOR_MIN_NODE_VERSION, DOCTOR_DAEMON_READY_TIMEOUT_MS, DOCTOR_DAEMON_WAIT_HEARTBEAT_MS, NODE_PACKAGE_SPEC, CODEX_INSTALL_SPEC, CLAUDE_INSTALL_SPEC, nodeVersionChecker, npmChecker, cliVersionChecker, windowsNativeLauncherChecker, providerBindingChecker, providerCliChecker, gatewayPluginChecker, gatewayConfigChecker, daemonChecker, agentRefreshChecker, gatewayReachableChecker, autostartChecker, CHECKERS, STATUS_MARK;
118188
+ var import_node_path37, DOCTOR_MIN_NODE_VERSION, DOCTOR_DAEMON_READY_TIMEOUT_MS, DOCTOR_DAEMON_WAIT_HEARTBEAT_MS, NODE_PACKAGE_SPEC, CODEX_INSTALL_SPEC, CLAUDE_INSTALL_SPEC, nodeVersionChecker, npmChecker, cliVersionChecker, windowsNativeLauncherChecker, providerBindingChecker, providerCliChecker, gatewayPluginChecker, gatewayConfigChecker, daemonChecker, agentRefreshChecker, gatewayReachableChecker, autostartChecker, CHECKERS, STATUS_MARK;
117541
118189
  var init_doctor_cli = __esm({
117542
118190
  "src/doctor-cli.ts"() {
117543
118191
  "use strict";
117544
- import_node_path36 = require("node:path");
118192
+ import_node_path37 = require("node:path");
117545
118193
  init_log();
117546
118194
  init_win_compat();
117547
118195
  init_ai_command();
@@ -117728,7 +118376,7 @@ var init_doctor_cli = __esm({
117728
118376
  command: "okx-a2a doctor --fix"
117729
118377
  },
117730
118378
  data: {
117731
- appDataNpm: ctx.env.APPDATA ? (0, import_node_path36.join)(ctx.env.APPDATA, "npm") : null
118379
+ appDataNpm: ctx.env.APPDATA ? (0, import_node_path37.join)(ctx.env.APPDATA, "npm") : null
117732
118380
  }
117733
118381
  };
117734
118382
  },
@@ -118335,7 +118983,7 @@ var init_doctor_cli = __esm({
118335
118983
  var import_node_child_process11 = require("node:child_process");
118336
118984
  var import_node_fs30 = require("node:fs");
118337
118985
  var import_node_os15 = require("node:os");
118338
- var import_node_path37 = require("node:path");
118986
+ var import_node_path38 = require("node:path");
118339
118987
  init_daemon();
118340
118988
  init_command_store();
118341
118989
  init_file_store();
@@ -118351,7 +118999,7 @@ init_sentry_logger();
118351
118999
  init_sentry_config();
118352
119000
  var CURRENT_GATEWAY_SESSION_KEYS_ENV4 = "OKX_A2A_CURRENT_GATEWAY_SESSION_KEYS";
118353
119001
  function printUsage3() {
118354
- console.log(`okx-a2a ${"0.2.7"}
119002
+ console.log(`okx-a2a ${"0.2.8-beta-912b775358-260818171144"}
118355
119003
 
118356
119004
  Usage:
118357
119005
  okx-a2a <command> [options]
@@ -118391,7 +119039,7 @@ Run \`okx-a2a <command> -h\` for command-specific help.
118391
119039
  `);
118392
119040
  }
118393
119041
  function printVersion() {
118394
- console.log("0.2.7");
119042
+ console.log("0.2.8-beta-912b775358-260818171144");
118395
119043
  }
118396
119044
  function printDaemonUsage() {
118397
119045
  console.log(`Usage: okx-a2a daemon <start|restart|stop|status|autostart> [options]
@@ -118665,7 +119313,7 @@ function maybeRedirectDaemonSelfLog() {
118665
119313
  }
118666
119314
  try {
118667
119315
  const logPath = resolveTaskPaths().listenerLogPath;
118668
- (0, import_node_fs30.mkdirSync)((0, import_node_path37.join)(logPath, ".."), { recursive: true });
119316
+ (0, import_node_fs30.mkdirSync)((0, import_node_path38.join)(logPath, ".."), { recursive: true });
118669
119317
  const fd = (0, import_node_fs30.openSync)(logPath, "a");
118670
119318
  const writeToLog = ((chunk, encoding, cb) => {
118671
119319
  try {
@@ -118772,7 +119420,7 @@ async function handleLogs(args) {
118772
119420
  return;
118773
119421
  }
118774
119422
  if (subcommand === "llm") {
118775
- await tailLogFile((0, import_node_path37.join)(paths.logsDir, "llm.log"));
119423
+ await tailLogFile((0, import_node_path38.join)(paths.logsDir, "llm.log"));
118776
119424
  return;
118777
119425
  }
118778
119426
  throw new Error("logs requires <server|llm|export>");
@@ -119694,7 +120342,7 @@ function initDirectCliSentry() {
119694
120342
  }
119695
120343
  cliSentryInitAttempted = true;
119696
120344
  try {
119697
- const configPath = (0, import_node_path37.join)(resolveTaskHomeForSentryConfig(), "xmtp", "system-config.json");
120345
+ const configPath = (0, import_node_path38.join)(resolveTaskHomeForSentryConfig(), "xmtp", "system-config.json");
119698
120346
  if (!(0, import_node_fs30.existsSync)(configPath)) {
119699
120347
  return;
119700
120348
  }
@@ -119718,11 +120366,11 @@ function resolveTaskHomeForSentryConfig() {
119718
120366
  try {
119719
120367
  const home = (0, import_node_os15.homedir)();
119720
120368
  if (home) {
119721
- return (0, import_node_path37.join)(home, ".okx-agent-task");
120369
+ return (0, import_node_path38.join)(home, ".okx-agent-task");
119722
120370
  }
119723
120371
  } catch {
119724
120372
  }
119725
- return (0, import_node_path37.resolve)(process.cwd(), ".okx-agent-task");
120373
+ return (0, import_node_path38.resolve)(process.cwd(), ".okx-agent-task");
119726
120374
  }
119727
120375
  function directCliSentryExtra(operation, extra = {}) {
119728
120376
  return {
@@ -119830,7 +120478,7 @@ async function main() {
119830
120478
  if (command === "xmtp-test") {
119831
120479
  const { handleXmtpTestCommand: handleXmtpTestCommand2 } = await Promise.resolve().then(() => (init_xmtp_test_cli(), xmtp_test_cli_exports));
119832
120480
  await handleXmtpTestCommand2(process.argv.slice(3), {
119833
- packageVersion: "0.2.7",
120481
+ packageVersion: "0.2.8-beta-912b775358-260818171144",
119834
120482
  agentSdkVersion: "2.3.0",
119835
120483
  nodeSdkVersion: "6.1.0",
119836
120484
  nodeBindingsVersion: "1.11.0"