@okxweb3/a2a-node 0.0.13-beta-d0ec14bc63-260622192924 → 0.0.13

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 +4427 -4155
  2. package/dist/index.js +1373 -1167
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1589,7 +1589,7 @@ var require_misc = __commonJS({
1589
1589
  }
1590
1590
  }
1591
1591
  var SEMVER_REGEXP = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/;
1592
- function parseSemver2(input) {
1592
+ function parseSemver3(input) {
1593
1593
  const match = input.match(SEMVER_REGEXP) || [];
1594
1594
  const major = parseInt(match[1], 10);
1595
1595
  const minor = parseInt(match[2], 10);
@@ -1631,7 +1631,7 @@ var require_misc = __commonJS({
1631
1631
  exports2.arrayify = arrayify;
1632
1632
  exports2.checkOrSetAlreadyCaught = checkOrSetAlreadyCaught;
1633
1633
  exports2.getEventDescription = getEventDescription;
1634
- exports2.parseSemver = parseSemver2;
1634
+ exports2.parseSemver = parseSemver3;
1635
1635
  exports2.uuid4 = uuid4;
1636
1636
  }
1637
1637
  });
@@ -1913,7 +1913,7 @@ var require_path = __commonJS({
1913
1913
  function isAbsolute2(path) {
1914
1914
  return path.charAt(0) === "/";
1915
1915
  }
1916
- function join19(...args) {
1916
+ function join18(...args) {
1917
1917
  return normalizePath(args.join("/"));
1918
1918
  }
1919
1919
  function dirname6(path) {
@@ -1938,7 +1938,7 @@ var require_path = __commonJS({
1938
1938
  exports2.basename = basename3;
1939
1939
  exports2.dirname = dirname6;
1940
1940
  exports2.isAbsolute = isAbsolute2;
1941
- exports2.join = join19;
1941
+ exports2.join = join18;
1942
1942
  exports2.normalizePath = normalizePath;
1943
1943
  exports2.relative = relative;
1944
1944
  exports2.resolve = resolve4;
@@ -67932,7 +67932,6 @@ __export(index_exports, {
67932
67932
  GatewayOutboundBehavior: () => GatewayOutboundBehavior,
67933
67933
  InvalidXmtpMessageStore: () => InvalidXmtpMessageStore,
67934
67934
  OFFLINE_REPLAY_SYNC_INTERVAL: () => OFFLINE_REPLAY_SYNC_INTERVAL,
67935
- OPENCLAW_GATEWAY_ROUTE_GROUP_ID: () => OPENCLAW_GATEWAY_ROUTE_GROUP_ID,
67936
67935
  SYSTEM_NOTIFICATION_SESSION_KEY: () => SYSTEM_NOTIFICATION_SESSION_KEY,
67937
67936
  SessionStore: () => SessionStore,
67938
67937
  SqliteOutboundBehavior: () => SqliteOutboundBehavior,
@@ -67946,7 +67945,6 @@ __export(index_exports, {
67946
67945
  bindJobProviderToCurrentDefaultIfMissing: () => bindJobProviderToCurrentDefaultIfMissing,
67947
67946
  bindJobProviderToCurrentRuntimeIfMissing: () => bindJobProviderToCurrentRuntimeIfMissing,
67948
67947
  bindMessageJobProviderToCurrentDefault: () => bindMessageJobProviderToCurrentDefault,
67949
- bindOpenClawGatewayRouteFromEnv: () => bindOpenClawGatewayRouteFromEnv,
67950
67948
  buildAgentMessageNotice: () => buildAgentMessageNotice,
67951
67949
  buildAiAdapterCommand: () => buildAiAdapterCommand,
67952
67950
  buildAiProviderEnv: () => buildAiProviderEnv,
@@ -67967,18 +67965,19 @@ __export(index_exports, {
67967
67965
  createFileMessageHandler: () => createFileMessageHandler,
67968
67966
  createOutboundBehavior: () => createOutboundBehavior,
67969
67967
  createUserAttentionWatchParentMonitor: () => createUserAttentionWatchParentMonitor,
67970
- currentOpenClawGatewaySessionKey: () => currentOpenClawGatewaySessionKey,
67971
67968
  detectAiProviders: () => detectAiProviders,
67972
67969
  detectCurrentAiProvider: () => detectCurrentAiProvider,
67973
67970
  detectGatewayInvocation: () => detectGatewayInvocation,
67974
67971
  detectRuntime: () => detectRuntime,
67972
+ ensureCommunicationMinVersions: () => ensureCommunicationMinVersions,
67975
67973
  ensureDefaultAiProvider: () => ensureDefaultAiProvider,
67976
67974
  extractAiSessionId: () => extractAiSessionId,
67977
- extractXmtpSentAtMs: () => extractXmtpSentAtMs,
67975
+ extractXmtpSentAtMs: () => extractXmtpSentAtMs2,
67978
67976
  getDaemonStatus: () => getDaemonStatus,
67979
67977
  handleXmtpSendCommand: () => handleXmtpSendCommand,
67980
67978
  hasAiRuntimeMarker: () => hasAiRuntimeMarker,
67981
67979
  heartbeatUserAttentionWatcher: () => heartbeatUserAttentionWatcher,
67980
+ isBelowRequiredVersion: () => isBelowRequiredVersion,
67982
67981
  isOriginalParentProcessAlive: () => isOriginalParentProcessAlive,
67983
67982
  isPrereleaseVersion: () => isPrereleaseVersion,
67984
67983
  isRetryableOpenClawGatewayError: () => isRetryableOpenClawGatewayError,
@@ -68001,8 +68000,6 @@ __export(index_exports, {
68001
68000
  resolveConfiguredAiProviderForJob: () => resolveConfiguredAiProviderForJob,
68002
68001
  resolveDirectCommunicationSessionTarget: () => resolveDirectCommunicationSessionTarget,
68003
68002
  resolveOpenClawGatewayConfig: () => resolveOpenClawGatewayConfig,
68004
- resolveOpenClawGatewayRoute: () => resolveOpenClawGatewayRoute,
68005
- resolveOpenClawGatewayRoutes: () => resolveOpenClawGatewayRoutes,
68006
68003
  resolveSystemNotificationTargets: () => resolveSystemNotificationTargets,
68007
68004
  resolveTaskConfigPath: () => resolveTaskConfigPath,
68008
68005
  resolveTaskHome: () => resolveTaskHome,
@@ -68561,10 +68558,6 @@ var SessionStore = class {
68561
68558
  VALUES (?, ?, ?, ?)
68562
68559
  ON CONFLICT(job_id) DO UPDATE SET
68563
68560
  provider = excluded.provider,
68564
- gateway_routes_json = CASE
68565
- WHEN job_provider_bindings.provider = excluded.provider THEN job_provider_bindings.gateway_routes_json
68566
- ELSE NULL
68567
- END,
68568
68561
  updated_at = excluded.updated_at
68569
68562
  `).run(params.jobId, params.provider, now, now);
68570
68563
  const binding = this.getJobProviderBinding(params.jobId);
@@ -68573,52 +68566,43 @@ var SessionStore = class {
68573
68566
  }
68574
68567
  return binding;
68575
68568
  }
68576
- setJobProviderGatewayRoutes(params) {
68569
+ upsertJobGatewayRoute(params) {
68577
68570
  assertNonEmpty(params.jobId, "jobId");
68578
- assertAiProvider(params.provider);
68579
- const routesJson = JSON.stringify(normalizeGatewayRouteBindings(params.routes));
68571
+ assertNonEmpty(params.route.platform, "route.platform");
68572
+ assertNonEmpty(params.route.chatId, "route.chatId");
68573
+ if (params.provider) {
68574
+ assertAiProvider(params.provider);
68575
+ }
68580
68576
  const now = this.timestamp();
68581
68577
  return this.transaction(() => {
68582
- this.db.prepare(`
68583
- INSERT OR IGNORE INTO job_provider_bindings(job_id, provider, created_at, updated_at)
68584
- VALUES (?, ?, ?, ?)
68585
- `).run(params.jobId, params.provider, now, now);
68586
68578
  const existing = this.getJobProviderBinding(params.jobId);
68587
68579
  if (!existing) {
68588
- throw new Error(`Failed to read job_provider_bindings ${params.jobId} before route update`);
68589
- }
68590
- if (existing.provider !== params.provider) {
68591
- return existing;
68580
+ this.db.prepare(`
68581
+ INSERT INTO job_provider_bindings(job_id, provider, gateway_routes_json, created_at, updated_at)
68582
+ VALUES (?, ?, ?, ?, ?)
68583
+ `).run(
68584
+ params.jobId,
68585
+ params.provider ?? "hermes",
68586
+ JSON.stringify([normalizeGatewayRoute(params.route, now)]),
68587
+ now,
68588
+ now
68589
+ );
68590
+ } else {
68591
+ const route = normalizeGatewayRoute(params.route, now);
68592
+ const routes = upsertGatewayRoute(existing.gatewayRoutes, route);
68593
+ this.db.prepare(`
68594
+ UPDATE job_provider_bindings
68595
+ SET gateway_routes_json = ?, updated_at = ?
68596
+ WHERE job_id = ?
68597
+ `).run(JSON.stringify(routes), now, params.jobId);
68592
68598
  }
68593
- this.db.prepare(`
68594
- UPDATE job_provider_bindings
68595
- SET gateway_routes_json = ?, updated_at = ?
68596
- WHERE job_id = ? AND provider = ?
68597
- `).run(routesJson, now, params.jobId, params.provider);
68598
68599
  const binding = this.getJobProviderBinding(params.jobId);
68599
68600
  if (!binding) {
68600
- throw new Error(`Failed to read job_provider_bindings ${params.jobId} after route update`);
68601
+ throw new Error(`Failed to read job_provider_bindings ${params.jobId} after route upsert`);
68601
68602
  }
68602
68603
  return binding;
68603
68604
  });
68604
68605
  }
68605
- clearJobProviderGatewayRoutes(params) {
68606
- assertNonEmpty(params.jobId, "jobId");
68607
- if (params.provider) {
68608
- assertAiProvider(params.provider);
68609
- }
68610
- const now = this.timestamp();
68611
- const result = params.provider ? this.db.prepare(`
68612
- UPDATE job_provider_bindings
68613
- SET gateway_routes_json = NULL, updated_at = ?
68614
- WHERE job_id = ? AND provider = ?
68615
- `).run(now, params.jobId, params.provider) : this.db.prepare(`
68616
- UPDATE job_provider_bindings
68617
- SET gateway_routes_json = NULL, updated_at = ?
68618
- WHERE job_id = ?
68619
- `).run(now, params.jobId);
68620
- return Number(result.changes ?? 0) > 0;
68621
- }
68622
68606
  deleteJobProviderBinding(jobId) {
68623
68607
  assertNonEmpty(jobId, "jobId");
68624
68608
  const result = this.db.prepare("DELETE FROM job_provider_bindings WHERE job_id = ?").run(jobId);
@@ -69393,54 +69377,82 @@ function mapJobProviderBindingRow(row) {
69393
69377
  return {
69394
69378
  jobId: row.job_id,
69395
69379
  provider: row.provider,
69396
- ...row.gateway_routes_json ? { gatewayRoutes: parseGatewayRouteBindings(row.gateway_routes_json) } : {},
69380
+ gatewayRoutes: parseGatewayRoutes(row.gateway_routes_json),
69397
69381
  createdAt: row.created_at,
69398
69382
  updatedAt: row.updated_at
69399
69383
  };
69400
69384
  }
69401
- function parseGatewayRouteBindings(value) {
69385
+ function parseGatewayRoutes(value) {
69386
+ if (!value) {
69387
+ return [];
69388
+ }
69402
69389
  try {
69403
69390
  const parsed = JSON.parse(value);
69404
69391
  if (!Array.isArray(parsed)) {
69405
69392
  return [];
69406
69393
  }
69407
- return normalizeGatewayRouteBindings(parsed);
69394
+ return parsed.flatMap((item) => {
69395
+ const route = normalizeGatewayRouteInput(item);
69396
+ return route ? [route] : [];
69397
+ });
69408
69398
  } catch {
69409
69399
  return [];
69410
69400
  }
69411
69401
  }
69412
- function normalizeGatewayRouteBindings(value) {
69413
- if (!Array.isArray(value)) {
69414
- return [];
69402
+ function normalizeGatewayRouteInput(value) {
69403
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
69404
+ return null;
69415
69405
  }
69416
- const routes = [];
69417
- for (const item of value) {
69418
- if (!item || typeof item !== "object") {
69419
- continue;
69420
- }
69421
- const record = item;
69422
- const platform = normalizeOptionalString(record.platform);
69423
- const sessionKey = normalizeOptionalString(record.sessionKey);
69424
- if (!platform || !sessionKey) {
69425
- continue;
69426
- }
69427
- const gatewaySessionKey = normalizeOptionalString(record.gatewaySessionKey);
69428
- const chatId = normalizeOptionalString(record.chatId);
69429
- const threadId = normalizeOptionalString(record.threadId);
69430
- const updatedAt = normalizeOptionalString(record.updatedAt);
69431
- routes.push({
69432
- platform,
69433
- sessionKey,
69434
- ...gatewaySessionKey ? { gatewaySessionKey } : {},
69435
- ...chatId ? { chatId } : {},
69436
- ...threadId ? { threadId } : {},
69437
- ...updatedAt ? { updatedAt } : {}
69438
- });
69406
+ const item = value;
69407
+ const platform = readText(item.platform);
69408
+ const chatId = readText(item.chatId) ?? readText(item.chat_id);
69409
+ if (!platform || !chatId) {
69410
+ return null;
69439
69411
  }
69440
- return routes;
69412
+ return {
69413
+ platform,
69414
+ chatId,
69415
+ chatName: readText(item.chatName) ?? readText(item.chat_name) ?? "",
69416
+ chatType: readText(item.chatType) ?? readText(item.chat_type) ?? (readText(item.threadId) || readText(item.thread_id) ? "thread" : "dm"),
69417
+ threadId: readText(item.threadId) ?? readText(item.thread_id) ?? "",
69418
+ userId: readText(item.userId) ?? readText(item.user_id) ?? "",
69419
+ userName: readText(item.userName) ?? readText(item.user_name) ?? "",
69420
+ sessionKey: readText(item.sessionKey) ?? readText(item.session_key) ?? "",
69421
+ gatewaySessionKey: readText(item.gatewaySessionKey) ?? readText(item.gateway_session_key) ?? "",
69422
+ updatedAt: readText(item.updatedAt) ?? readText(item.updated_at) ?? ""
69423
+ };
69424
+ }
69425
+ function normalizeGatewayRoute(route, updatedAt) {
69426
+ return {
69427
+ platform: route.platform,
69428
+ chatId: route.chatId,
69429
+ chatName: route.chatName ?? "",
69430
+ chatType: route.chatType || (route.threadId ? "thread" : "dm"),
69431
+ threadId: route.threadId ?? "",
69432
+ userId: route.userId ?? "",
69433
+ userName: route.userName ?? "",
69434
+ sessionKey: route.sessionKey ?? route.gatewaySessionKey ?? "",
69435
+ gatewaySessionKey: route.gatewaySessionKey ?? route.sessionKey ?? "",
69436
+ updatedAt
69437
+ };
69438
+ }
69439
+ function upsertGatewayRoute(routes, route) {
69440
+ const key = gatewayRouteKey(route);
69441
+ const next = routes.filter((item) => gatewayRouteKey(item) !== key);
69442
+ next.push(route);
69443
+ return next;
69444
+ }
69445
+ function gatewayRouteKey(route) {
69446
+ return `${route.platform}
69447
+ ${route.chatId}
69448
+ ${route.threadId ?? ""}`;
69441
69449
  }
69442
- function normalizeOptionalString(value) {
69443
- return typeof value === "string" && value.trim() ? value.trim() : null;
69450
+ function readText(value) {
69451
+ if (typeof value !== "string") {
69452
+ return null;
69453
+ }
69454
+ const trimmed = value.trim();
69455
+ return trimmed || null;
69444
69456
  }
69445
69457
 
69446
69458
  // src/daemon-lock.ts
@@ -69587,6 +69599,7 @@ async function ensureDaemonDirs(homeDir) {
69587
69599
  }
69588
69600
  async function ensureAiWorkspace(paths) {
69589
69601
  const aiWorkingDir = paths.workspaceDir;
69602
+ await (0, import_promises2.rm)(aiWorkingDir, { recursive: true, force: true });
69590
69603
  ensureTaskDir(aiWorkingDir);
69591
69604
  return aiWorkingDir;
69592
69605
  }
@@ -69779,6 +69792,32 @@ async function stopDaemon(homeDir) {
69779
69792
  };
69780
69793
  }
69781
69794
 
69795
+ // ../core/src/log.ts
69796
+ function formatLogTimestamp(date = /* @__PURE__ */ new Date()) {
69797
+ return date.toLocaleString(void 0, {
69798
+ year: "numeric",
69799
+ month: "2-digit",
69800
+ day: "2-digit",
69801
+ hour: "2-digit",
69802
+ minute: "2-digit",
69803
+ second: "2-digit",
69804
+ fractionalSecondDigits: 3,
69805
+ hour12: false
69806
+ });
69807
+ }
69808
+ function prefixArgs(args) {
69809
+ return [`[${formatLogTimestamp()}]`, ...args];
69810
+ }
69811
+ function logWithTimestamp(...args) {
69812
+ console.log(...prefixArgs(args));
69813
+ }
69814
+ function warnWithTimestamp(...args) {
69815
+ console.warn(...prefixArgs(args));
69816
+ }
69817
+ function errorWithTimestamp(...args) {
69818
+ console.error(...prefixArgs(args));
69819
+ }
69820
+
69782
69821
  // src/ai-runner.ts
69783
69822
  var import_node_crypto3 = require("node:crypto");
69784
69823
  var import_node_fs7 = require("node:fs");
@@ -70282,7 +70321,7 @@ function detectGatewayInvocation(env = process.env) {
70282
70321
  if (!isTruthyRuntimeMarker(env.OKX_A2A_IN_GATEWAY)) {
70283
70322
  return null;
70284
70323
  }
70285
- const provider = env.OKX_A2A_GATEWAY_PROVIDER ?? env.OKX_A2A_AI_PROVIDER ?? env.OKX_AGENT_TASK_AI_CLI;
70324
+ const provider = env.OKX_A2A_GATEWAY_PROVIDER;
70286
70325
  if (!provider) {
70287
70326
  return null;
70288
70327
  }
@@ -70935,6 +70974,7 @@ var LogEvent = {
70935
70974
  USER_DISPATCHED: "User dispatched",
70936
70975
  SESSION_DISPATCHED: "Session dispatched",
70937
70976
  SYNC_TICK_COMPLETED: "Sync tick completed",
70977
+ INBOUND_HANDLER_ENTERED: "Inbound handler entered",
70938
70978
  MESSAGE_RECEIVED: "Message received",
70939
70979
  MESSAGE_SENT: "Message sent",
70940
70980
  INBOUND_BUYER_PENDING: "Inbound buyer: no session, group still Unknown (pending)",
@@ -70972,6 +71012,8 @@ var LogEvent = {
70972
71012
  AGENTS_WAKEUP_NOTIFIED: "Agents wakeup notified",
70973
71013
  CONFIG_SENSITIVE_WORDS_REFRESHED: "Sensitive words config refreshed",
70974
71014
  CONFIG_SYSTEM_REFRESHED: "System config refreshed",
71015
+ FORCED_UPDATE_STARTED: "Forced update started",
71016
+ FORCED_UPDATE_SUCCEEDED: "Forced update succeeded",
70975
71017
  GATEWAY_DISCONNECTED: "Gateway disconnected",
70976
71018
  GATEWAY_REQUEST: "Gateway request",
70977
71019
  GATEWAY_DELIVERY_BUFFERED: "Gateway delivery buffered",
@@ -70982,6 +71024,9 @@ var LogEvent = {
70982
71024
  USER_WATCH_EVENT_DELIVERED: "User watch event delivered",
70983
71025
  INBOUND_DM_RAW: "Inbound DM raw",
70984
71026
  INBOUND_GROUP_RAW: "Inbound group raw",
71027
+ SYSTEM_NOTIFICATION_RECEIVED: "System notification received",
71028
+ SYSTEM_NOTIFICATION_ROUTED: "System notification routed",
71029
+ HERMES_SESSION_ROUTE_BINDING: "Hermes session route binding",
70985
71030
  // ── error ─────────────────────────────────────────────────────
70986
71031
  XMTP_CONNECTION_FAILED: "XMTP connection failed",
70987
71032
  CONVERSATIONS_STREAM_FAILED: "conversations.stream failed",
@@ -71031,6 +71076,7 @@ var LogEvent = {
71031
71076
  CACHE_LOAD_FAILED: "Cache load failed",
71032
71077
  CACHE_WRITE_FAILED: "Cache write failed",
71033
71078
  CONFIG_LOAD_FAILED: "Config load failed",
71079
+ FORCED_UPDATE_FAILED: "Forced update failed",
71034
71080
  SENTRY_INIT_SKIPPED: "Sentry init skipped",
71035
71081
  AGENT_DB_DIR_CREATE_FAILED: "Agent DB dir create failed"
71036
71082
  };
@@ -71180,6 +71226,9 @@ var SENTRY_INFO_ALLOWLIST = /* @__PURE__ */ new Set([
71180
71226
  LogEvent.INBOUND_DELIVERED,
71181
71227
  LogEvent.INBOUND_DM_RAW,
71182
71228
  LogEvent.INBOUND_GROUP_RAW,
71229
+ LogEvent.SYSTEM_NOTIFICATION_RECEIVED,
71230
+ LogEvent.SYSTEM_NOTIFICATION_ROUTED,
71231
+ LogEvent.HERMES_SESSION_ROUTE_BINDING,
71183
71232
  LogEvent.INBOUND_BLOCKED_ADDRESS_MISMATCH,
71184
71233
  LogEvent.INBOUND_BLOCKED_INELIGIBLE,
71185
71234
  LogEvent.INBOUND_BLOCKED_SENSITIVE,
@@ -71204,10 +71253,13 @@ var SENTRY_INFO_ALLOWLIST = /* @__PURE__ */ new Set([
71204
71253
  LogEvent.BOOTSTRAP_APPLIED,
71205
71254
  LogEvent.CONFIG_SENSITIVE_WORDS_REFRESHED,
71206
71255
  LogEvent.CONFIG_SYSTEM_REFRESHED,
71256
+ LogEvent.FORCED_UPDATE_STARTED,
71257
+ LogEvent.FORCED_UPDATE_SUCCEEDED,
71207
71258
  LogEvent.CONVERSATION_HISTORY_QUERIED,
71208
71259
  LogEvent.FILE_DOWNLOADED,
71209
71260
  LogEvent.FILE_UPLOADED,
71210
71261
  LogEvent.GROUP_CONSENT_CHANGED,
71262
+ LogEvent.INBOUND_HANDLER_ENTERED,
71211
71263
  LogEvent.MESSAGE_RECEIVED,
71212
71264
  LogEvent.OFFLINE_REPLAY_MESSAGE_REPLAYED,
71213
71265
  LogEvent.AGENT_REFRESH_SESSION_EXPIRED,
@@ -71235,7 +71287,7 @@ var SentryLogger = class _SentryLogger {
71235
71287
  }
71236
71288
  init(config) {
71237
71289
  if (this.initialized) {
71238
- console.warn("[logger] Already initialized, skipping.");
71290
+ warnWithTimestamp("[logger] Already initialized, skipping.");
71239
71291
  return;
71240
71292
  }
71241
71293
  try {
@@ -71545,7 +71597,7 @@ async function runAiAdapter(options) {
71545
71597
  const permissionPreset = options.permissionPreset ?? (options.provider === "codex" || options.provider === "claude" ? resolveAiPermissionPresetForRun(homeDir, options.env ?? process.env) : void 0);
71546
71598
  const built = buildAiAdapterCommand({ ...options, homeDir, permissionPreset });
71547
71599
  const startedAt = Date.now();
71548
- console.error(
71600
+ errorWithTimestamp(
71549
71601
  `[okx-agent-task] AI adapter start provider=${options.provider} command=${built.command} mode=${options.sessionId ? "resume" : "new"} cwd=${options.cwd ?? process.cwd()}`
71550
71602
  );
71551
71603
  const child = (0, import_node_child_process3.spawn)(built.command, built.args, {
@@ -71623,7 +71675,7 @@ async function runAiAdapter(options) {
71623
71675
  if (trailingStderr) {
71624
71676
  sessionId = trailingStderr;
71625
71677
  }
71626
- console.error(
71678
+ errorWithTimestamp(
71627
71679
  `[okx-agent-task] AI adapter done provider=${options.provider} exitCode=${exitCode ?? "null"} sessionId=${sessionId ?? "(none)"} duration=${durationMs}ms timeout=${timedOut ? "yes" : "no"} stdout=${stdout.length}B stderr=${stderr.length}B`
71628
71680
  );
71629
71681
  if (timedOut || exitCode !== 0 || !sessionId) {
@@ -72071,18 +72123,20 @@ var AiRunner = class {
72071
72123
  const normalized = this.normalizeRunRequest(request);
72072
72124
  const queueKey = this.buildRunQueueKey(normalized);
72073
72125
  const triggeredAt = normalized.triggeredAtMs ?? Date.now();
72074
- await this.appendLlmLog({
72075
- type: "trigger",
72076
- source: normalized.source,
72077
- sessionKey: normalized.sessionKey,
72078
- jobId: normalized.jobId,
72079
- agentId: normalized.agentId,
72080
- messageId: normalized.messageId,
72081
- queueKey,
72082
- triggeredAtMs: triggeredAt,
72083
- commandPendingMs: normalized.commandPendingMs,
72084
- content: normalized.prompt
72085
- });
72126
+ if (isAiLifecycleLoggingEnabled()) {
72127
+ await this.appendLlmLog({
72128
+ type: "trigger",
72129
+ source: normalized.source,
72130
+ sessionKey: normalized.sessionKey,
72131
+ jobId: normalized.jobId,
72132
+ agentId: normalized.agentId,
72133
+ messageId: normalized.messageId,
72134
+ queueKey,
72135
+ triggeredAtMs: triggeredAt,
72136
+ commandPendingMs: normalized.commandPendingMs,
72137
+ content: normalized.prompt
72138
+ });
72139
+ }
72086
72140
  const enqueuedAt = Date.now();
72087
72141
  const previous = this.dispatchQueues.get(queueKey) ?? Promise.resolve();
72088
72142
  const next = previous.catch(() => void 0).then(() => this.runUnlocked(normalized, enqueuedAt, triggeredAt));
@@ -72128,7 +72182,7 @@ var AiRunner = class {
72128
72182
  }
72129
72183
  async runUnlocked(request, enqueuedAt, triggeredAt) {
72130
72184
  if (process.env.OKX_AGENT_TASK_DISABLE_AI === "1") {
72131
- console.error("[okx-agent-task] AI dispatch disabled by OKX_AGENT_TASK_DISABLE_AI=1");
72185
+ errorWithTimestamp("[okx-agent-task] AI dispatch disabled by OKX_AGENT_TASK_DISABLE_AI=1");
72132
72186
  return;
72133
72187
  }
72134
72188
  try {
@@ -72143,8 +72197,9 @@ var AiRunner = class {
72143
72197
  const queueWaitMs = dispatchStartedAt - enqueuedAt;
72144
72198
  const commandPendingMs = request.commandPendingMs ?? 0;
72145
72199
  ensureTaskDir(this.logsDir);
72146
- const logPath = this.buildRunLogPath(request);
72147
- const log = (0, import_node_fs7.createWriteStream)(logPath, { flags: "a" });
72200
+ const lifecycleLogsEnabled = isAiLifecycleLoggingEnabled();
72201
+ const logPath = lifecycleLogsEnabled ? this.buildRunLogPath(request) : "";
72202
+ const log = lifecycleLogsEnabled ? (0, import_node_fs7.createWriteStream)(logPath, { flags: "a" }) : null;
72148
72203
  let existing = null;
72149
72204
  let storeReadStartedAt;
72150
72205
  let storeReadEndedAt;
@@ -72183,7 +72238,7 @@ var AiRunner = class {
72183
72238
  const toolFailures = createAiToolFailureTracker(provider);
72184
72239
  const captureAiSessionId = (candidate) => {
72185
72240
  if (existingAiSessionId && candidate !== existingAiSessionId) {
72186
- console.error(
72241
+ errorWithTimestamp(
72187
72242
  `[okx-agent-task] ignoring mismatched ${provider} session id ${this.formatRunTarget(request)} expected=${existingAiSessionId} got=${candidate}`
72188
72243
  );
72189
72244
  return;
@@ -72259,7 +72314,7 @@ var AiRunner = class {
72259
72314
  firstStdoutAt ??= Date.now();
72260
72315
  stdoutFull += chunk.toString("utf8");
72261
72316
  stdoutText = appendOutput(stdoutText, chunk);
72262
- log.write(chunk);
72317
+ log?.write(chunk);
72263
72318
  parseStdoutChunk(chunk);
72264
72319
  });
72265
72320
  child.stderr?.on("data", (chunk) => {
@@ -72267,7 +72322,7 @@ var AiRunner = class {
72267
72322
  const text = chunk.toString("utf8");
72268
72323
  stderrFull += text;
72269
72324
  stderrText += text;
72270
- log.write(chunk);
72325
+ log?.write(chunk);
72271
72326
  parseStderrText(text);
72272
72327
  });
72273
72328
  const target = formatDispatchTarget({
@@ -72277,7 +72332,7 @@ var AiRunner = class {
72277
72332
  messageId: request.messageId
72278
72333
  });
72279
72334
  const label = request.source === "job-dispatch" ? "AI dispatch" : "AI session";
72280
- console.error(
72335
+ errorWithTimestamp(
72281
72336
  `[okx-agent-task] ${label} start ${target} provider=${provider} mode=${existingAiSessionId ? "resume" : "new"} pid=${child.pid ?? "unknown"} commandPending=${commandPendingMs ?? ""}ms queue=${queueWaitMs}ms prepare=${Date.now() - dispatchStartedAt}ms storeRead=${storeReadMs ?? ""}ms providerResolve=${resolveMs}ms cwd=${aiCwd} log=${logPath}`
72282
72337
  );
72283
72338
  const timeout = timeoutMs === null ? null : setTimeout(() => {
@@ -72286,7 +72341,7 @@ var AiRunner = class {
72286
72341
  `;
72287
72342
  stderrFull += message;
72288
72343
  stderrText += message;
72289
- log.write(message);
72344
+ log?.write(message);
72290
72345
  console.error(message.trim());
72291
72346
  child.kill("SIGTERM");
72292
72347
  setTimeout(() => {
@@ -72319,9 +72374,11 @@ var AiRunner = class {
72319
72374
  const sessionWriteEndedAt = Date.now();
72320
72375
  const sessionWriteMs = sessionWriteEndedAt - sessionWriteStartedAt;
72321
72376
  const logFileCloseStartedAt = Date.now();
72322
- await new Promise((resolve4) => {
72323
- log.end(resolve4);
72324
- });
72377
+ if (log) {
72378
+ await new Promise((resolve4) => {
72379
+ log.end(resolve4);
72380
+ });
72381
+ }
72325
72382
  const logFileCloseEndedAt = Date.now();
72326
72383
  const totalMs = logFileCloseEndedAt - triggeredAt;
72327
72384
  const trailingStdoutLine = stdoutBuffer.trim();
@@ -72365,7 +72422,7 @@ var AiRunner = class {
72365
72422
  aiSessionId,
72366
72423
  timedOut
72367
72424
  });
72368
- console.error(
72425
+ errorWithTimestamp(
72369
72426
  `[okx-agent-task] ${label} done ${target} provider=${provider} exitCode=${exitCode ?? "null"} signal=${closeResult.signal ?? "none"} timeout=${timedOut ? "yes" : "no"} aiSession=${shortenValue(aiSessionId)} commandPending=${commandPendingMs ?? ""}ms queue=${queueWaitMs}ms cli=${cliMs}ms sessionWrite=${sessionWriteMs}ms total=${totalMs}ms result=${summarizeAiOutput(stdoutText, stderrText)}`
72370
72427
  );
72371
72428
  const aiFailureExtra = (reason) => aiRunSentryExtra({
@@ -72390,56 +72447,58 @@ var AiRunner = class {
72390
72447
  timeToFirstStdoutMs: firstStdoutAt === null ? null : firstStdoutAt - spawnedAt,
72391
72448
  timeToFirstStderrMs: firstStderrAt === null ? null : firstStderrAt - spawnedAt
72392
72449
  });
72393
- await this.appendLlmLog({
72394
- type: "ai-output",
72395
- source: request.source,
72396
- sessionKey: request.sessionKey,
72397
- jobId: request.jobId,
72398
- agentId: request.agentId,
72399
- messageId: request.messageId,
72400
- provider,
72401
- mode: existingAiSessionId ? "resume" : "new",
72402
- pid: child.pid ?? null,
72403
- cwd: aiCwd,
72404
- logPath,
72405
- exitCode,
72406
- closeSignal: closeResult.signal,
72407
- aiSessionId,
72408
- timedOut,
72409
- timeoutMs,
72410
- triggeredAtMs: triggeredAt,
72411
- enqueuedAtMs: enqueuedAt,
72412
- runStartedAtMs: dispatchStartedAt,
72413
- storeReadStartedAtMs: storeReadStartedAt,
72414
- storeReadEndedAtMs: storeReadEndedAt,
72415
- providerResolveStartedAtMs: resolveStartedAt,
72416
- providerResolveEndedAtMs: resolveEndedAt,
72417
- spawnStartedAtMs: spawnStartedAt,
72418
- spawnedAtMs: spawnedAt,
72419
- firstStdoutAtMs: firstStdoutAt,
72420
- firstStderrAtMs: firstStderrAt,
72421
- childClosedAtMs: childClosedAt,
72422
- sessionWriteStartedAtMs: sessionWriteStartedAt,
72423
- sessionWriteEndedAtMs: sessionWriteEndedAt,
72424
- logFileCloseStartedAtMs: logFileCloseStartedAt,
72425
- logFileCloseEndedAtMs: logFileCloseEndedAt,
72426
- commandPendingMs,
72427
- queueWaitMs,
72428
- triggerToEnqueueMs: enqueuedAt - triggeredAt,
72429
- runStartToSpawnMs: spawnedAt - dispatchStartedAt,
72430
- storeReadMs,
72431
- providerResolveMs: resolveMs,
72432
- timeToFirstStdoutMs: firstStdoutAt === null ? null : firstStdoutAt - spawnedAt,
72433
- timeToFirstStderrMs: firstStderrAt === null ? null : firstStderrAt - spawnedAt,
72434
- spawnToCloseMs: childClosedAt - spawnedAt,
72435
- runStartToCloseMs: childClosedAt - dispatchStartedAt,
72436
- sessionWriteMs,
72437
- logFileCloseMs: logFileCloseEndedAt - logFileCloseStartedAt,
72438
- cliMs,
72439
- totalMs,
72440
- stdout: stdoutFull,
72441
- stderr: stderrFull
72442
- });
72450
+ if (lifecycleLogsEnabled) {
72451
+ await this.appendLlmLog({
72452
+ type: "ai-output",
72453
+ source: request.source,
72454
+ sessionKey: request.sessionKey,
72455
+ jobId: request.jobId,
72456
+ agentId: request.agentId,
72457
+ messageId: request.messageId,
72458
+ provider,
72459
+ mode: existingAiSessionId ? "resume" : "new",
72460
+ pid: child.pid ?? null,
72461
+ cwd: aiCwd,
72462
+ logPath,
72463
+ exitCode,
72464
+ closeSignal: closeResult.signal,
72465
+ aiSessionId,
72466
+ timedOut,
72467
+ timeoutMs,
72468
+ triggeredAtMs: triggeredAt,
72469
+ enqueuedAtMs: enqueuedAt,
72470
+ runStartedAtMs: dispatchStartedAt,
72471
+ storeReadStartedAtMs: storeReadStartedAt,
72472
+ storeReadEndedAtMs: storeReadEndedAt,
72473
+ providerResolveStartedAtMs: resolveStartedAt,
72474
+ providerResolveEndedAtMs: resolveEndedAt,
72475
+ spawnStartedAtMs: spawnStartedAt,
72476
+ spawnedAtMs: spawnedAt,
72477
+ firstStdoutAtMs: firstStdoutAt,
72478
+ firstStderrAtMs: firstStderrAt,
72479
+ childClosedAtMs: childClosedAt,
72480
+ sessionWriteStartedAtMs: sessionWriteStartedAt,
72481
+ sessionWriteEndedAtMs: sessionWriteEndedAt,
72482
+ logFileCloseStartedAtMs: logFileCloseStartedAt,
72483
+ logFileCloseEndedAtMs: logFileCloseEndedAt,
72484
+ commandPendingMs,
72485
+ queueWaitMs,
72486
+ triggerToEnqueueMs: enqueuedAt - triggeredAt,
72487
+ runStartToSpawnMs: spawnedAt - dispatchStartedAt,
72488
+ storeReadMs,
72489
+ providerResolveMs: resolveMs,
72490
+ timeToFirstStdoutMs: firstStdoutAt === null ? null : firstStdoutAt - spawnedAt,
72491
+ timeToFirstStderrMs: firstStderrAt === null ? null : firstStderrAt - spawnedAt,
72492
+ spawnToCloseMs: childClosedAt - spawnedAt,
72493
+ runStartToCloseMs: childClosedAt - dispatchStartedAt,
72494
+ sessionWriteMs,
72495
+ logFileCloseMs: logFileCloseEndedAt - logFileCloseStartedAt,
72496
+ cliMs,
72497
+ totalMs,
72498
+ stdout: stdoutFull,
72499
+ stderr: stderrFull
72500
+ });
72501
+ }
72443
72502
  if (isMissingResumeSessionFailure({
72444
72503
  provider,
72445
72504
  existingAiSessionId,
@@ -72451,7 +72510,7 @@ var AiRunner = class {
72451
72510
  provider,
72452
72511
  request
72453
72512
  });
72454
- console.error(
72513
+ errorWithTimestamp(
72455
72514
  `[okx-agent-task] ${provider} resume session is unavailable; retrying ${target} as a new session without prior context.`
72456
72515
  );
72457
72516
  return this.runAi(request, enqueuedAt, triggeredAt, true);
@@ -72624,30 +72683,6 @@ var AiRunner = class {
72624
72683
  });
72625
72684
  }
72626
72685
  }
72627
- buildArgs(provider, event, aiSessionId, cwd = this.resolveAiWorkingDir()) {
72628
- const sessionKey = buildDispatchSessionKey(event.jobId, event.sessionAgentId);
72629
- return this.buildRunArgs(provider, {
72630
- source: "job-dispatch",
72631
- sessionKey,
72632
- prompt: this.buildPrompt(event),
72633
- jobId: event.jobId,
72634
- agentId: event.sessionAgentId,
72635
- messageId: event.message.id,
72636
- jobFilePath: event.jobFilePath,
72637
- sessionAgentId: event.sessionAgentId
72638
- }, aiSessionId, cwd);
72639
- }
72640
- buildSessionArgs(provider, event, aiSessionId, cwd = this.resolveAiWorkingDir()) {
72641
- const messageId = event.messageId ?? `session-${Date.now()}`;
72642
- return this.buildRunArgs(provider, {
72643
- source: "session-message",
72644
- sessionKey: event.sessionKey,
72645
- prompt: this.buildSessionPrompt({ ...event, messageId }),
72646
- jobId: event.jobId,
72647
- agentId: event.agentId,
72648
- messageId
72649
- }, aiSessionId, cwd);
72650
- }
72651
72686
  buildRunArgs(provider, request, aiSessionId, cwd = this.resolveAiWorkingDir()) {
72652
72687
  const permissionPreset = this.resolveAiPermissionPresetForRun();
72653
72688
  const prompt = request.prompt;
@@ -72795,7 +72830,7 @@ var AiRunner = class {
72795
72830
  logPath: runContext?.logPath
72796
72831
  })
72797
72832
  );
72798
- console.error("[okx-agent-task] failed to create user_attention for AI run failure:", attentionErr);
72833
+ errorWithTimestamp("[okx-agent-task] failed to create user_attention for AI run failure:", attentionErr);
72799
72834
  }
72800
72835
  }
72801
72836
  async reportAiToolFailures(failures, context) {
@@ -72847,7 +72882,7 @@ var AiRunner = class {
72847
72882
  reason: "user_attention_create_failed"
72848
72883
  }
72849
72884
  );
72850
- console.error("[okx-agent-task] failed to create user_attention for AI tool failure:", attentionErr);
72885
+ errorWithTimestamp("[okx-agent-task] failed to create user_attention for AI tool failure:", attentionErr);
72851
72886
  }
72852
72887
  }
72853
72888
  }
@@ -72862,7 +72897,7 @@ var AiRunner = class {
72862
72897
  ensureTaskDir(this.logsDir);
72863
72898
  await (0, import_promises5.appendFile)((0, import_node_path11.join)(this.logsDir, "llm.log"), formatLlmLogEntry(entry), "utf8");
72864
72899
  } catch (err2) {
72865
- console.error("[okx-agent-task] failed to append llm.log:", err2);
72900
+ errorWithTimestamp("[okx-agent-task] failed to append llm.log:", err2);
72866
72901
  }
72867
72902
  }
72868
72903
  };
@@ -72892,6 +72927,13 @@ function aiRunToolFailureSentryExtra(failure, context) {
72892
72927
  return out;
72893
72928
  }, {});
72894
72929
  }
72930
+ function isAiLifecycleLoggingEnabled(env = process.env) {
72931
+ const raw = env.OKX_A2A_AI_LIFECYCLE_LOGS ?? env.OKX_AGENT_TASK_AI_LIFECYCLE_LOGS;
72932
+ if (!raw) {
72933
+ return true;
72934
+ }
72935
+ return !["0", "false", "no", "off"].includes(raw.trim().toLowerCase());
72936
+ }
72895
72937
  function safeProcessCwd() {
72896
72938
  try {
72897
72939
  return process.cwd();
@@ -74175,7 +74217,6 @@ var CommandStore = class {
74175
74217
  myAgentId: params.myAgentId,
74176
74218
  toAgentId: params.toAgentId,
74177
74219
  toXmtpAddress: params.toXmtpAddress,
74178
- gatewaySessionKeys: params.gatewaySessionKeys,
74179
74220
  createdAt: Date.now()
74180
74221
  };
74181
74222
  }
@@ -74339,7 +74380,7 @@ var CommandStore = class {
74339
74380
  });
74340
74381
  continue;
74341
74382
  }
74342
- console.log(`[okx-agent-task] invalid queued command row id=${row.id} type=${row.type}`);
74383
+ logWithTimestamp(`[okx-agent-task] invalid queued command row id=${row.id} type=${row.type}`);
74343
74384
  }
74344
74385
  return commands;
74345
74386
  }
@@ -74411,7 +74452,7 @@ var CommandStore = class {
74411
74452
  status === "processing" ? mtimeMs : null
74412
74453
  );
74413
74454
  } catch (err2) {
74414
- console.log(`[okx-agent-task] failed to import legacy command ${path}:`, err2);
74455
+ logWithTimestamp(`[okx-agent-task] failed to import legacy command ${path}:`, err2);
74415
74456
  }
74416
74457
  }
74417
74458
  }
@@ -76771,6 +76812,53 @@ function selfFilterMiddleware() {
76771
76812
  };
76772
76813
  }
76773
76814
 
76815
+ // ../core/src/xmtp-sdk/inbound-timing.ts
76816
+ function createInboundTimingTracker(xmtpSentAtMs, xmtpReceivedAtMs = Date.now()) {
76817
+ const durations = {};
76818
+ return {
76819
+ xmtpSentAtMs,
76820
+ xmtpReceivedAtMs,
76821
+ xmtpDeliveryMs: safeDuration(xmtpReceivedAtMs, xmtpSentAtMs),
76822
+ mark(stage, startedAtMs) {
76823
+ const key = stage.endsWith("Ms") ? stage : `${stage}Ms`;
76824
+ const durationMs = safeDuration(Date.now(), startedAtMs);
76825
+ durations[key] = durationMs;
76826
+ return durationMs;
76827
+ },
76828
+ extras(extra = {}) {
76829
+ return {
76830
+ xmtpSentAtMs,
76831
+ xmtpReceivedAtMs,
76832
+ xmtpDeliveryMs: safeDuration(xmtpReceivedAtMs, xmtpSentAtMs),
76833
+ handlerTotalMs: safeDuration(Date.now(), xmtpReceivedAtMs),
76834
+ ...durations,
76835
+ ...extra
76836
+ };
76837
+ }
76838
+ };
76839
+ }
76840
+ function extractXmtpSentAtMs(msg) {
76841
+ if (typeof msg.sentAtNs === "bigint") {
76842
+ return Number(msg.sentAtNs / 1000000n);
76843
+ }
76844
+ if (typeof msg.sentAtNs === "number") {
76845
+ return Math.floor(msg.sentAtNs / 1e6);
76846
+ }
76847
+ if (msg.sentAt instanceof Date) {
76848
+ return msg.sentAt.getTime();
76849
+ }
76850
+ if (typeof msg.sentAt === "number") {
76851
+ return msg.sentAt;
76852
+ }
76853
+ return Date.now();
76854
+ }
76855
+ function safeDuration(endMs, startMs) {
76856
+ if (!Number.isFinite(endMs) || !Number.isFinite(startMs)) {
76857
+ return 0;
76858
+ }
76859
+ return Math.max(0, Math.round(endMs - startMs));
76860
+ }
76861
+
76774
76862
  // ../core/src/xmtp-sdk/middleware/logging.ts
76775
76863
  function loggingMiddleware(identity3) {
76776
76864
  const tag = `[xmtp-sdk:${identity3.walletAddress ?? "?"}]`;
@@ -76778,46 +76866,38 @@ function loggingMiddleware(identity3) {
76778
76866
  const msg = ctx.message;
76779
76867
  const conv = ctx.conversation;
76780
76868
  const conversationId = conv.id;
76869
+ const xmtpReceivedAtMs = Date.now();
76870
+ const xmtpSentAtMs = extractXmtpSentAtMs(msg);
76871
+ const ownInboxId = ctx.client?.inboxId ?? identity3.inboxId ?? "";
76781
76872
  const content3 = JSON.stringify(msg);
76782
76873
  const contentSummary = summarizeMessageContent(msg.content);
76783
76874
  const baseExtras = {
76784
76875
  ...agentExtras(identity3),
76785
76876
  ...jobIdExtras(msg.content),
76786
76877
  peerInboxId: msg.senderInboxId,
76878
+ senderInboxId: msg.senderInboxId,
76879
+ ownInboxId,
76787
76880
  conversationId,
76788
76881
  messageId: msg.id,
76789
- stage: "inbound/transport_received"
76882
+ kind: msg.kind ?? "unknown",
76883
+ source: "live",
76884
+ xmtpSentAtMs: String(xmtpSentAtMs),
76885
+ xmtpReceivedAtMs: String(xmtpReceivedAtMs),
76886
+ xmtpDeliveryMs: String(safeDuration(xmtpReceivedAtMs, xmtpSentAtMs)),
76887
+ stage: "inbound/stream_observed"
76790
76888
  };
76791
76889
  if (conv instanceof Group) {
76792
76890
  const groupName = conv.name ?? "unnamed";
76793
- let memberCount = "0";
76794
- let membersInfo = "";
76795
- let membersFetchFailed = "0";
76796
- try {
76797
- const members = await conv.members();
76798
- memberCount = String(members.length);
76799
- const addresses = members.flatMap(
76800
- (m) => m.accountIdentifiers.map((id) => id.identifier)
76801
- );
76802
- membersInfo = ` members=[${addresses.join(", ")}]`;
76803
- } catch (err2) {
76804
- console.log(`${tag} [group] members fetch failed:`, err2);
76805
- memberCount = "fetch-failed";
76806
- membersInfo = " members=[fetch failed]";
76807
- membersFetchFailed = "1";
76808
- }
76809
- console.log(
76810
- `${tag} [group] conv=${conversationId} name="${groupName}"${membersInfo} sender=${msg.senderInboxId} msg=${msg.id} bytes=${content3.length} ${contentSummary}`
76891
+ logWithTimestamp(
76892
+ `${tag} [group] conv=${conversationId} name="${groupName}" sender=${msg.senderInboxId} msg=${msg.id} bytes=${content3.length} ${contentSummary}`
76811
76893
  );
76812
76894
  logger.info(LogEvent.MESSAGE_RECEIVED, {
76813
76895
  ...baseExtras,
76814
76896
  chatType: "group",
76815
- groupName,
76816
- memberCount,
76817
- membersFetchFailed
76897
+ groupName
76818
76898
  });
76819
76899
  } else {
76820
- console.log(
76900
+ logWithTimestamp(
76821
76901
  `${tag} [dm] conv=${conversationId} sender=${msg.senderInboxId} msg=${msg.id} bytes=${content3.length} ${contentSummary}`
76822
76902
  );
76823
76903
  logger.info(LogEvent.MESSAGE_RECEIVED, {
@@ -83103,11 +83183,11 @@ async function createAgentWithInstallationPrune(signer, options, context) {
83103
83183
  if (!oldest) {
83104
83184
  throw err2;
83105
83185
  }
83106
- console.log(
83186
+ logWithTimestamp(
83107
83187
  `${prefix} installation cap reached for ${context.address} (agentId=${context.agentId}); revoking oldest installation ${oldest.id}`
83108
83188
  );
83109
83189
  await Client.revokeInstallations(signer, inboxId, [oldest.bytes], options.env, options.gatewayHost);
83110
- console.log(
83190
+ logWithTimestamp(
83111
83191
  `${prefix} revoked oldest installation for ${context.address} (agentId=${context.agentId}); retrying client init`
83112
83192
  );
83113
83193
  return await Agent.create(signer, options);
@@ -83201,7 +83281,7 @@ function loadSensitiveWordsFromCache(dataDir) {
83201
83281
  }
83202
83282
  return null;
83203
83283
  } catch (err2) {
83204
- console.log("[xmtp-sdk] failed to read sensitive-words.json cache:", err2);
83284
+ logWithTimestamp("[xmtp-sdk] failed to read sensitive-words.json cache:", err2);
83205
83285
  logger.error(LogEvent.CACHE_LOAD_FAILED, err2 instanceof Error ? err2 : new Error(String(err2)), { cacheName: "sensitive-words" });
83206
83286
  return null;
83207
83287
  }
@@ -83211,19 +83291,19 @@ function saveSensitiveWordsToCache(dataDir, words) {
83211
83291
  ensureCacheDir(dataDir);
83212
83292
  (0, import_node_fs10.writeFileSync)(cachePath(dataDir, "sensitive-words.json"), JSON.stringify(words));
83213
83293
  } catch (err2) {
83214
- console.log(`[xmtp-sdk] failed to write sensitive-words.json:`, err2);
83294
+ logWithTimestamp(`[xmtp-sdk] failed to write sensitive-words.json:`, err2);
83215
83295
  logger.error(LogEvent.CACHE_WRITE_FAILED, err2 instanceof Error ? err2 : new Error(String(err2)), { cacheName: "sensitive-words" });
83216
83296
  }
83217
83297
  }
83218
83298
  async function loadSensitiveWordsWith(dataDir, fetcher) {
83219
83299
  if (!fetcher) {
83220
- console.log("[xmtp-sdk] sensitive-words fetcher not provided by host");
83300
+ logWithTimestamp("[xmtp-sdk] sensitive-words fetcher not provided by host");
83221
83301
  return loadSensitiveWordsFromCache(dataDir);
83222
83302
  }
83223
83303
  const cached = loadSensitiveWordsFromCache(dataDir);
83224
83304
  try {
83225
83305
  const words = await fetcher();
83226
- console.log(`[xmtp-sdk] fetched ${words.length} sensitive words from API`);
83306
+ logWithTimestamp(`[xmtp-sdk] fetched ${words.length} sensitive words from API`);
83227
83307
  saveSensitiveWordsToCache(dataDir, words);
83228
83308
  logger.info(LogEvent.CONFIG_SENSITIVE_WORDS_REFRESHED, {
83229
83309
  count: String(words.length),
@@ -83231,17 +83311,17 @@ async function loadSensitiveWordsWith(dataDir, fetcher) {
83231
83311
  });
83232
83312
  return words;
83233
83313
  } catch (err2) {
83234
- console.log(`[xmtp-sdk] API fetch for sensitive words failed:`, err2);
83314
+ logWithTimestamp(`[xmtp-sdk] API fetch for sensitive words failed:`, err2);
83235
83315
  }
83236
83316
  if (cached) {
83237
- console.log(`[xmtp-sdk] using ${cached.length} cached sensitive words from disk`);
83317
+ logWithTimestamp(`[xmtp-sdk] using ${cached.length} cached sensitive words from disk`);
83238
83318
  logger.info(LogEvent.CONFIG_SENSITIVE_WORDS_REFRESHED, {
83239
83319
  count: String(cached.length),
83240
83320
  source: "cache"
83241
83321
  });
83242
83322
  return cached;
83243
83323
  }
83244
- console.log(`[xmtp-sdk] sensitive-words load failed: neither API nor local cache available`);
83324
+ logWithTimestamp(`[xmtp-sdk] sensitive-words load failed: neither API nor local cache available`);
83245
83325
  logger.error(LogEvent.CONFIG_LOAD_FAILED, void 0, {
83246
83326
  config: "sensitive-words",
83247
83327
  reason: "no-api-no-cache"
@@ -83260,7 +83340,7 @@ function loadSystemConfigFromCache(dataDir) {
83260
83340
  }
83261
83341
  return null;
83262
83342
  } catch (err2) {
83263
- console.log("[xmtp-sdk] failed to read system-config.json cache:", err2);
83343
+ logWithTimestamp("[xmtp-sdk] failed to read system-config.json cache:", err2);
83264
83344
  logger.error(LogEvent.CACHE_LOAD_FAILED, err2 instanceof Error ? err2 : new Error(String(err2)), { cacheName: "system-config" });
83265
83345
  return null;
83266
83346
  }
@@ -83270,18 +83350,18 @@ function saveSystemConfigToCache(dataDir, config) {
83270
83350
  ensureCacheDir(dataDir);
83271
83351
  (0, import_node_fs10.writeFileSync)(cachePath(dataDir, "system-config.json"), JSON.stringify(config));
83272
83352
  } catch (err2) {
83273
- console.log(`[xmtp-sdk] failed to write system-config.json:`, err2);
83353
+ logWithTimestamp(`[xmtp-sdk] failed to write system-config.json:`, err2);
83274
83354
  logger.error(LogEvent.CACHE_WRITE_FAILED, err2 instanceof Error ? err2 : new Error(String(err2)), { cacheName: "system-config" });
83275
83355
  }
83276
83356
  }
83277
83357
  async function loadSystemConfigWith(dataDir, fetcher) {
83278
83358
  if (!fetcher) {
83279
- console.log("[xmtp-sdk] system-config fetcher not provided by host");
83359
+ logWithTimestamp("[xmtp-sdk] system-config fetcher not provided by host");
83280
83360
  return loadSystemConfigFromCache(dataDir);
83281
83361
  }
83282
83362
  try {
83283
83363
  const config = await fetcher();
83284
- console.log(
83364
+ logWithTimestamp(
83285
83365
  `[xmtp-sdk] fetched system-config from API: ${Object.keys(config).length} keys`
83286
83366
  );
83287
83367
  saveSystemConfigToCache(dataDir, config);
@@ -83291,11 +83371,11 @@ async function loadSystemConfigWith(dataDir, fetcher) {
83291
83371
  });
83292
83372
  return config;
83293
83373
  } catch (err2) {
83294
- console.log(`[xmtp-sdk] API fetch for system-config failed:`, err2);
83374
+ logWithTimestamp(`[xmtp-sdk] API fetch for system-config failed:`, err2);
83295
83375
  }
83296
83376
  const cached = loadSystemConfigFromCache(dataDir);
83297
83377
  if (cached) {
83298
- console.log(
83378
+ logWithTimestamp(
83299
83379
  `[xmtp-sdk] using cached system-config from disk: ${Object.keys(cached).length} keys`
83300
83380
  );
83301
83381
  logger.info(LogEvent.CONFIG_SYSTEM_REFRESHED, {
@@ -83304,7 +83384,7 @@ async function loadSystemConfigWith(dataDir, fetcher) {
83304
83384
  });
83305
83385
  return cached;
83306
83386
  }
83307
- console.log(`[xmtp-sdk] system-config load failed: neither API nor local cache available`);
83387
+ logWithTimestamp(`[xmtp-sdk] system-config load failed: neither API nor local cache available`);
83308
83388
  logger.error(LogEvent.CONFIG_LOAD_FAILED, void 0, {
83309
83389
  config: "system-config",
83310
83390
  reason: "no-api-no-cache"
@@ -83328,7 +83408,7 @@ function loadSyncByAddress(dataDir) {
83328
83408
  }
83329
83409
  }
83330
83410
  } catch (err2) {
83331
- console.log("[xmtp-sdk] failed to read last-sync.json cache:", err2);
83411
+ logWithTimestamp("[xmtp-sdk] failed to read last-sync.json cache:", err2);
83332
83412
  logger.error(LogEvent.CACHE_LOAD_FAILED, err2 instanceof Error ? err2 : new Error(String(err2)), { cacheName: "last-sync" });
83333
83413
  }
83334
83414
  return map;
@@ -83352,7 +83432,7 @@ function saveSyncForAddress(dataDir, address, timestampMs) {
83352
83432
  data.syncByAddress[address] = timestampMs;
83353
83433
  (0, import_node_fs10.writeFileSync)(path, JSON.stringify(data, null, 2));
83354
83434
  } catch (err2) {
83355
- console.log(
83435
+ logWithTimestamp(
83356
83436
  `[xmtp-sdk] failed to write last-sync.json (address=${address}):`,
83357
83437
  err2
83358
83438
  );
@@ -83461,6 +83541,18 @@ function parseTips(raw) {
83461
83541
  function parseStringArray(raw) {
83462
83542
  return Array.isArray(raw) ? raw.filter((value) => typeof value === "string" && value.length > 0) : [];
83463
83543
  }
83544
+ function readOptionalString(record, key) {
83545
+ const value = record[key];
83546
+ return typeof value === "string" ? value : "";
83547
+ }
83548
+ function readMinVersion(raw) {
83549
+ const container = raw.minVersion && typeof raw.minVersion === "object" && !Array.isArray(raw.minVersion) ? raw.minVersion : raw.minVersions && typeof raw.minVersions === "object" && !Array.isArray(raw.minVersions) ? raw.minVersions : {};
83550
+ return {
83551
+ cli: readOptionalString(container, "cli") || readOptionalString(raw, "cliMinVersion"),
83552
+ openclaw: readOptionalString(container, "openclaw") || readOptionalString(raw, "openclawMinVersion"),
83553
+ hermes: readOptionalString(container, "hermes") || readOptionalString(raw, "hermesMinVersion")
83554
+ };
83555
+ }
83464
83556
  function parseExtConfig(raw) {
83465
83557
  const obj = raw && typeof raw === "object" && !Array.isArray(raw) ? raw : {};
83466
83558
  return {
@@ -83482,13 +83574,14 @@ function parseSystemConfig(raw) {
83482
83574
  acc.push({ address, inboxId, type });
83483
83575
  return acc;
83484
83576
  }, []) : [];
83577
+ const minVersion = readMinVersion(raw);
83485
83578
  return {
83486
83579
  heartbeatInterval: typeof raw.heartbeatInterval === "number" ? raw.heartbeatInterval : SYSTEM_CONFIG_DEFAULTS.heartbeatInterval,
83487
83580
  maxFileSizeBytes: typeof raw.maxFileSizeBytes === "number" && Number.isFinite(raw.maxFileSizeBytes) && raw.maxFileSizeBytes > 0 ? raw.maxFileSizeBytes : SYSTEM_CONFIG_DEFAULTS.maxFileSizeBytes,
83488
83581
  sensitiveUploadReg: parseStringArray(raw.SENSITIVE_UPLOAD_REG),
83489
83582
  accounts,
83490
83583
  sentryDsn: typeof raw.sentryDsn === "string" ? raw.sentryDsn : "",
83491
- minAvailablePluginVersion: typeof raw.minAvailablePluginVersion === "string" ? raw.minAvailablePluginVersion : "",
83584
+ minVersion,
83492
83585
  extConfig: parseExtConfig(raw.extConfig)
83493
83586
  };
83494
83587
  }
@@ -83537,11 +83630,7 @@ var XmtpService = class _XmtpService {
83537
83630
  _initFailures = [];
83538
83631
  _backupReady = Promise.resolve();
83539
83632
  _onAfterInitError = null;
83540
- _pluginVersion = "";
83541
- _pluginVersionStatus = {
83542
- unavailable: false,
83543
- minVersion: ""
83544
- };
83633
+ _cliVersion = "";
83545
83634
  dataDir = DEFAULT_DATA_DIR;
83546
83635
  syncByAddress = /* @__PURE__ */ new Map();
83547
83636
  agentListFingerprint;
@@ -83572,12 +83661,12 @@ var XmtpService = class _XmtpService {
83572
83661
  return this.dataDir;
83573
83662
  }
83574
83663
  async init() {
83575
- console.log("[xmtp-sdk] init: loading system-config first to gate on plugin version...");
83664
+ logWithTimestamp("[xmtp-sdk] init: loading system-config first to gate on plugin version...");
83576
83665
  this._initFailures = [];
83577
83666
  try {
83578
83667
  ensureA2aTaskDir(this.dataDir);
83579
83668
  } catch (err2) {
83580
- console.log(`[xmtp-sdk] failed to create data directory: ${this.dataDir}`, err2);
83669
+ logWithTimestamp(`[xmtp-sdk] failed to create data directory: ${this.dataDir}`, err2);
83581
83670
  logger.error(
83582
83671
  LogEvent.AGENT_DB_DIR_CREATE_FAILED,
83583
83672
  err2 instanceof Error ? err2 : new Error(String(err2)),
@@ -83589,11 +83678,11 @@ var XmtpService = class _XmtpService {
83589
83678
  ]);
83590
83679
  if (systemConfigResult.status === "fulfilled" && systemConfigResult.value) {
83591
83680
  this.systemConfig = parseSystemConfig(systemConfigResult.value);
83592
- this.evaluatePluginVersion();
83593
- if (this._pluginVersionStatus.unavailable) {
83681
+ const cliMinVersion = this.systemConfig.minVersion.cli;
83682
+ if (this.isCliBelowMinVersion(cliMinVersion)) {
83594
83683
  this._initialized = false;
83595
- console.log(
83596
- `[xmtp-sdk] init aborted: plugin v${this._pluginVersion} is below the required minimum v${this._pluginVersionStatus.minVersion}. Run \`openclaw plugins update okx-a2a\` to upgrade.`
83684
+ logWithTimestamp(
83685
+ `[xmtp-sdk] init paused: cli v${this._cliVersion} is below the required minimum v${cliMinVersion}; daemon updater will attempt a forced update.`
83597
83686
  );
83598
83687
  return;
83599
83688
  }
@@ -83602,7 +83691,7 @@ var XmtpService = class _XmtpService {
83602
83691
  "loadSystemConfig returned null (neither API nor local cache is available)"
83603
83692
  );
83604
83693
  this._initFailures.push({ action: "loadSystemConfig", error: err2 });
83605
- console.log("[xmtp-sdk] init: loadSystemConfig failed:", err2.message);
83694
+ logWithTimestamp("[xmtp-sdk] init: loadSystemConfig failed:", err2.message);
83606
83695
  }
83607
83696
  const [sensitiveWordsResult, clientsResult] = await Promise.allSettled([
83608
83697
  loadSensitiveWordsWith(this.dataDir, this.tools.fetchSensitiveWords),
@@ -83612,7 +83701,7 @@ var XmtpService = class _XmtpService {
83612
83701
  this._onAfterInitError = null;
83613
83702
  this._backupReady = afterInit ? afterInit().catch((err2) => {
83614
83703
  this._onAfterInitError = err2 instanceof Error ? err2 : new Error(String(err2));
83615
- console.log(
83704
+ logWithTimestamp(
83616
83705
  "[xmtp-sdk] tools.onAfterInit failed (will retry on first use):",
83617
83706
  err2
83618
83707
  );
@@ -83622,39 +83711,36 @@ var XmtpService = class _XmtpService {
83622
83711
  } else {
83623
83712
  this.sensitiveWords = null;
83624
83713
  const reason = sensitiveWordsResult.status === "rejected" ? sensitiveWordsResult.reason : "loadSensitiveWords returned null (neither API nor local cache is available)";
83625
- console.log(
83714
+ logWithTimestamp(
83626
83715
  "[xmtp-sdk] init: loadSensitiveWords failed; will lazy-retry during message handling:",
83627
83716
  reason
83628
83717
  );
83629
83718
  }
83630
83719
  if (clientsResult.status === "fulfilled") {
83631
- console.log(
83720
+ logWithTimestamp(
83632
83721
  `[xmtp-sdk] init: XMTP clients initialized, ${clientsResult.value.size} clients`
83633
83722
  );
83634
83723
  } else {
83635
83724
  const err2 = clientsResult.reason instanceof Error ? clientsResult.reason : new Error(String(clientsResult.reason));
83636
83725
  this._initFailures.push({ action: "initXmtpInstall", error: err2 });
83637
- console.log("[xmtp-sdk] init: initXmtpInstall failed:", err2.message);
83726
+ logWithTimestamp("[xmtp-sdk] init: initXmtpInstall failed:", err2.message);
83638
83727
  }
83639
83728
  this._initialized = this._initFailures.length === 0;
83640
- if (this._initialized) {
83641
- this.evaluatePluginVersion();
83642
- }
83643
83729
  const clientCount = clientsResult.status === "fulfilled" ? clientsResult.value.size : 0;
83644
- console.log(
83730
+ logWithTimestamp(
83645
83731
  `[xmtp-sdk] init done: initialized=${this._initialized}, clients=${clientCount}, failures=${this._initFailures.length}`
83646
83732
  );
83647
83733
  }
83648
83734
  async retryFailedInit() {
83649
83735
  const remaining = [];
83650
83736
  for (const failure of this._initFailures) {
83651
- console.log(`[xmtp-sdk] retryFailedInit: retrying ${failure.action}...`);
83737
+ logWithTimestamp(`[xmtp-sdk] retryFailedInit: retrying ${failure.action}...`);
83652
83738
  try {
83653
83739
  if (failure.action === "loadSystemConfig") {
83654
83740
  const config = await loadSystemConfigWith(this.dataDir, this.tools.fetchSystemConfig);
83655
83741
  if (config) {
83656
83742
  this.systemConfig = parseSystemConfig(config);
83657
- console.log(
83743
+ logWithTimestamp(
83658
83744
  `[xmtp-sdk] retryFailedInit: loadSystemConfig retry succeeded`
83659
83745
  );
83660
83746
  } else {
@@ -83667,12 +83753,12 @@ var XmtpService = class _XmtpService {
83667
83753
  }
83668
83754
  } else if (failure.action === "initXmtpInstall") {
83669
83755
  await this.initXmtpInstall();
83670
- console.log(`[xmtp-sdk] retryFailedInit: initXmtpInstall retry succeeded`);
83756
+ logWithTimestamp(`[xmtp-sdk] retryFailedInit: initXmtpInstall retry succeeded`);
83671
83757
  }
83672
83758
  } catch (err2) {
83673
83759
  const error = err2 instanceof Error ? err2 : new Error(String(err2));
83674
83760
  remaining.push({ action: failure.action, error });
83675
- console.log(
83761
+ logWithTimestamp(
83676
83762
  `[xmtp-sdk] retryFailedInit: ${failure.action} retry failed:`,
83677
83763
  error.message
83678
83764
  );
@@ -83681,18 +83767,17 @@ var XmtpService = class _XmtpService {
83681
83767
  this._initFailures = remaining;
83682
83768
  if (remaining.length === 0) {
83683
83769
  this._initialized = true;
83684
- this.evaluatePluginVersion();
83685
83770
  }
83686
83771
  return { ok: remaining.length === 0, failures: remaining };
83687
83772
  }
83688
83773
  async initXmtpInstall() {
83689
- console.log(`==============XMTP_ENV: ${this.env}==============`);
83774
+ logWithTimestamp(`==============XMTP_ENV: ${this.env}==============`);
83690
83775
  const initStart = Date.now();
83691
83776
  const dbDir = this.dataDir;
83692
83777
  try {
83693
83778
  ensureA2aTaskDir(dbDir);
83694
83779
  } catch (err2) {
83695
- console.log(`[xmtp-sdk] failed to create data directory: ${dbDir}`, err2);
83780
+ logWithTimestamp(`[xmtp-sdk] failed to create data directory: ${dbDir}`, err2);
83696
83781
  logger.error(
83697
83782
  LogEvent.AGENT_DB_DIR_CREATE_FAILED,
83698
83783
  err2 instanceof Error ? err2 : new Error(String(err2)),
@@ -83701,7 +83786,7 @@ var XmtpService = class _XmtpService {
83701
83786
  return this.clients;
83702
83787
  }
83703
83788
  this.syncByAddress = loadSyncByAddress(this.dataDir);
83704
- console.log(
83789
+ logWithTimestamp(
83705
83790
  `[xmtp-sdk] sync timestamps: ${this.syncByAddress.size} addresses on record`
83706
83791
  );
83707
83792
  if (!this.tools.listAllAgentsWithMetadata) {
@@ -83714,7 +83799,7 @@ var XmtpService = class _XmtpService {
83714
83799
  this.agentListFingerprint = agentList.fingerprint;
83715
83800
  this.setAgentStatusIndex(agentList.allAgents ?? agentList.agents);
83716
83801
  const agents = agentList.agents;
83717
- console.log(
83802
+ logWithTimestamp(
83718
83803
  `[xmtp-sdk] fetched ${agents.length} agents from onchainos changed=${agentList.changed} duration=${agentList.durationMs}ms`
83719
83804
  );
83720
83805
  this.allAgents = agents;
@@ -83725,7 +83810,7 @@ var XmtpService = class _XmtpService {
83725
83810
  onchainosAgentIds: agents.map((a) => a.agentId).join(",")
83726
83811
  });
83727
83812
  }).catch((err2) => {
83728
- console.log("[xmtp-sdk] notifyAgentsWakeup unexpected error:", err2);
83813
+ logWithTimestamp("[xmtp-sdk] notifyAgentsWakeup unexpected error:", err2);
83729
83814
  logger.error(
83730
83815
  LogEvent.NOTIFY_AGENTS_WAKEUP_FAILED,
83731
83816
  err2 instanceof Error ? err2 : new Error(String(err2)),
@@ -83755,7 +83840,7 @@ var XmtpService = class _XmtpService {
83755
83840
  const { address, agent, agentInfo } = r.value;
83756
83841
  this.stoppedAddresses.delete(address.toLowerCase());
83757
83842
  this.clients.set(address, agent);
83758
- console.log(
83843
+ logWithTimestamp(
83759
83844
  `[xmtp-sdk] identity initialized: ${address} (agentId=${agentInfo.agentId})`
83760
83845
  );
83761
83846
  logger.info(LogEvent.AGENT_CLIENT_CREATED, {
@@ -83768,7 +83853,7 @@ var XmtpService = class _XmtpService {
83768
83853
  });
83769
83854
  } else {
83770
83855
  failedAgents.push(agents[i]);
83771
- console.log(
83856
+ logWithTimestamp(
83772
83857
  `[xmtp-sdk] identity init failed: ${agents[i].communicationAddress} (agentId=${agents[i].agentId})`,
83773
83858
  r.reason
83774
83859
  );
@@ -83784,7 +83869,7 @@ var XmtpService = class _XmtpService {
83784
83869
  }
83785
83870
  }
83786
83871
  if (failedAgents.length > 0) {
83787
- console.log(
83872
+ logWithTimestamp(
83788
83873
  `[xmtp-sdk] ${failedAgents.length} client(s) failed to initialize, retrying in 1s...`
83789
83874
  );
83790
83875
  await new Promise((r) => setTimeout(r, 1e3));
@@ -83795,7 +83880,7 @@ var XmtpService = class _XmtpService {
83795
83880
  const { address, agent, agentInfo } = r.value;
83796
83881
  this.stoppedAddresses.delete(address.toLowerCase());
83797
83882
  this.clients.set(address, agent);
83798
- console.log(
83883
+ logWithTimestamp(
83799
83884
  `[xmtp-sdk] retry succeeded: ${address} (agentId=${agentInfo.agentId})`
83800
83885
  );
83801
83886
  logger.info(LogEvent.AGENT_CLIENT_CREATED, {
@@ -83808,7 +83893,7 @@ var XmtpService = class _XmtpService {
83808
83893
  });
83809
83894
  } else {
83810
83895
  const info = failedAgents[i];
83811
- console.log(
83896
+ logWithTimestamp(
83812
83897
  `[xmtp-sdk] retry still failed: ${info.communicationAddress} (agentId=${info.agentId})`,
83813
83898
  r.reason
83814
83899
  );
@@ -83824,7 +83909,7 @@ var XmtpService = class _XmtpService {
83824
83909
  }
83825
83910
  }
83826
83911
  }
83827
- console.log(
83912
+ logWithTimestamp(
83828
83913
  `[xmtp-sdk] initialized ${this.clients.size}/${agents.length} clients in total`
83829
83914
  );
83830
83915
  await this.startListening();
@@ -83842,7 +83927,7 @@ var XmtpService = class _XmtpService {
83842
83927
  }
83843
83928
  async refreshAgents() {
83844
83929
  if (this.refreshAgentsInFlight) {
83845
- console.log(`[xmtp-sdk] refresh: a refresh is already in flight, reusing the same promise`);
83930
+ logWithTimestamp(`[xmtp-sdk] refresh: a refresh is already in flight, reusing the same promise`);
83846
83931
  return this.refreshAgentsInFlight;
83847
83932
  }
83848
83933
  this.refreshAgentsInFlight = this.runRefreshAgents().finally(() => {
@@ -83867,7 +83952,7 @@ var XmtpService = class _XmtpService {
83867
83952
  changed = agentList.changed;
83868
83953
  } catch (err2) {
83869
83954
  if (isSessionExpiredError(err2)) {
83870
- console.log(
83955
+ logWithTimestamp(
83871
83956
  "[xmtp-sdk] refresh: onchainos session expired, taking all local clients offline"
83872
83957
  );
83873
83958
  logger.info(LogEvent.AGENT_REFRESH_SESSION_EXPIRED, {
@@ -83901,11 +83986,11 @@ var XmtpService = class _XmtpService {
83901
83986
  try {
83902
83987
  this.stoppedAddresses.add(address.toLowerCase());
83903
83988
  client.stop();
83904
- console.log(
83989
+ logWithTimestamp(
83905
83990
  `[xmtp-sdk] refresh: stopped client: ${address} (agentId=${agentInfo.agentId})`
83906
83991
  );
83907
83992
  } catch (err2) {
83908
- console.log(`[xmtp-sdk] refresh: failed to stop client: ${address}`, err2);
83993
+ logWithTimestamp(`[xmtp-sdk] refresh: failed to stop client: ${address}`, err2);
83909
83994
  logger.error(LogEvent.AGENT_REFRESH_FAILED, err2 instanceof Error ? err2 : new Error(String(err2)), {
83910
83995
  walletAddress: address,
83911
83996
  onchainosAgentId: agentInfo.agentId,
@@ -83927,7 +84012,7 @@ var XmtpService = class _XmtpService {
83927
84012
  try {
83928
84013
  ensureA2aTaskDir(dbDir);
83929
84014
  } catch (err2) {
83930
- console.log(`[xmtp-sdk] refresh: failed to create data directory: ${dbDir}`, err2);
84015
+ logWithTimestamp(`[xmtp-sdk] refresh: failed to create data directory: ${dbDir}`, err2);
83931
84016
  logger.error(LogEvent.AGENT_REFRESH_FAILED, err2 instanceof Error ? err2 : new Error(String(err2)), {
83932
84017
  onchainosAgentId: "*",
83933
84018
  phase: "mkdir",
@@ -83964,7 +84049,7 @@ var XmtpService = class _XmtpService {
83964
84049
  const { address, agentInfo } = r.value;
83965
84050
  this.stoppedAddresses.delete(address.toLowerCase());
83966
84051
  this.clients.set(address, r.value.agent);
83967
- console.log(
84052
+ logWithTimestamp(
83968
84053
  `[xmtp-sdk] refresh: identity initialized: ${address} (agentId=${agentInfo.agentId})`
83969
84054
  );
83970
84055
  logger.info(LogEvent.AGENT_CLIENT_CREATED, {
@@ -83978,7 +84063,7 @@ var XmtpService = class _XmtpService {
83978
84063
  });
83979
84064
  } else {
83980
84065
  failedAgents.push(added[i]);
83981
- console.log(
84066
+ logWithTimestamp(
83982
84067
  `[xmtp-sdk] refresh: identity init failed: ${added[i].communicationAddress} (agentId=${added[i].agentId})`,
83983
84068
  r.reason
83984
84069
  );
@@ -83995,7 +84080,7 @@ var XmtpService = class _XmtpService {
83995
84080
  }
83996
84081
  }
83997
84082
  if (failedAgents.length > 0) {
83998
- console.log(
84083
+ logWithTimestamp(
83999
84084
  `[xmtp-sdk] refresh: ${failedAgents.length} client(s) failed to initialize, retrying in 1s...`
84000
84085
  );
84001
84086
  await new Promise((r) => setTimeout(r, 1e3));
@@ -84006,7 +84091,7 @@ var XmtpService = class _XmtpService {
84006
84091
  const { address, agentInfo } = r.value;
84007
84092
  this.stoppedAddresses.delete(address.toLowerCase());
84008
84093
  this.clients.set(address, r.value.agent);
84009
- console.log(
84094
+ logWithTimestamp(
84010
84095
  `[xmtp-sdk] refresh: retry succeeded: ${address} (agentId=${agentInfo.agentId})`
84011
84096
  );
84012
84097
  logger.info(LogEvent.AGENT_CLIENT_CREATED, {
@@ -84020,7 +84105,7 @@ var XmtpService = class _XmtpService {
84020
84105
  });
84021
84106
  } else {
84022
84107
  const info = failedAgents[i];
84023
- console.log(
84108
+ logWithTimestamp(
84024
84109
  `[xmtp-sdk] refresh: retry still failed: ${info.communicationAddress} (agentId=${info.agentId})`,
84025
84110
  r.reason
84026
84111
  );
@@ -84043,11 +84128,11 @@ var XmtpService = class _XmtpService {
84043
84128
  for (const agentInfo of added) {
84044
84129
  const address = agentInfo.communicationAddress;
84045
84130
  if (this.syncByAddress.has(address) && this.clients.has(address)) {
84046
- console.log(
84131
+ logWithTimestamp(
84047
84132
  `[xmtp-sdk] refresh: ${address} has a prior sync timestamp, triggering offline replay`
84048
84133
  );
84049
84134
  this.replayOfflineMessagesForAddress(address).catch((err2) => {
84050
- console.log(`[xmtp-sdk] refresh: ${address} offline replay failed:`, err2);
84135
+ logWithTimestamp(`[xmtp-sdk] refresh: ${address} offline replay failed:`, err2);
84051
84136
  logger.error(
84052
84137
  LogEvent.OFFLINE_REPLAY_FAILED,
84053
84138
  err2 instanceof Error ? err2 : new Error(String(err2)),
@@ -84155,13 +84240,13 @@ var XmtpService = class _XmtpService {
84155
84240
  );
84156
84241
  if (result !== null) {
84157
84242
  this.sensitiveWords = result;
84158
- console.log(
84243
+ logWithTimestamp(
84159
84244
  `[xmtp-sdk] lazy-retry sensitive-words succeeded: ${result.length} entries`
84160
84245
  );
84161
84246
  return result;
84162
84247
  }
84163
84248
  this.sensitiveWordsLastFailedAtMs = Date.now();
84164
- console.log(
84249
+ logWithTimestamp(
84165
84250
  "[xmtp-sdk] lazy-retry sensitive-words failed, entering cooldown"
84166
84251
  );
84167
84252
  return null;
@@ -84174,27 +84259,14 @@ var XmtpService = class _XmtpService {
84174
84259
  getSystemConfig() {
84175
84260
  return this.systemConfig;
84176
84261
  }
84177
- // The plugin reports its own build version (injected via esbuild
84178
- // define) before calling init(); we compare it once against
84179
- // systemConfig.minAvailablePluginVersion when init completes, then
84180
- // freeze the result. Tool guards read the cached status, so per-call
84181
- // semver work is avoided entirely.
84182
- setPluginVersion(version2) {
84183
- this._pluginVersion = version2 ?? "";
84184
- }
84185
- get pluginVersionStatus() {
84186
- return this._pluginVersionStatus;
84187
- }
84188
- evaluatePluginVersion() {
84189
- const min = this.systemConfig.minAvailablePluginVersion;
84190
- if (!min || !isValidSemver(min) || !isValidSemver(this._pluginVersion)) {
84191
- this._pluginVersionStatus = { unavailable: false, minVersion: min ?? "" };
84192
- return;
84193
- }
84194
- this._pluginVersionStatus = {
84195
- unavailable: semverLt(this._pluginVersion, min),
84196
- minVersion: min
84197
- };
84262
+ // The daemon reports its own build version before init(); startup can pause
84263
+ // before XMTP clients are created while the node listener performs the actual
84264
+ // forced update.
84265
+ setCliVersion(version2) {
84266
+ this._cliVersion = version2 ?? "";
84267
+ }
84268
+ isCliBelowMinVersion(minVersion) {
84269
+ return Boolean(minVersion) && isValidSemver(minVersion) && isValidSemver(this._cliVersion) && semverLt(this._cliVersion, minVersion);
84198
84270
  }
84199
84271
  // Force-refresh systemConfig from onchainos API (falls back to disk
84200
84272
  // cache). Single in-flight promise is shared by concurrent callers so
@@ -84209,7 +84281,6 @@ var XmtpService = class _XmtpService {
84209
84281
  const raw = await loadSystemConfigWith(this.dataDir, this.tools.fetchSystemConfig);
84210
84282
  if (raw) {
84211
84283
  this.systemConfig = parseSystemConfig(raw);
84212
- this.evaluatePluginVersion();
84213
84284
  }
84214
84285
  } finally {
84215
84286
  this.systemConfigRefreshInflight = null;
@@ -84260,7 +84331,7 @@ var XmtpService = class _XmtpService {
84260
84331
  async allowGroup(myXmtpAddress, groupId) {
84261
84332
  const agent = this.getClientByAddress(myXmtpAddress);
84262
84333
  if (!agent) {
84263
- console.log(
84334
+ logWithTimestamp(
84264
84335
  `[xmtp-sdk] allowGroup: no client found for address=${myXmtpAddress}`
84265
84336
  );
84266
84337
  logger.error(LogEvent.GROUP_CONSENT_UPDATE_FAILED, void 0, {
@@ -84281,7 +84352,7 @@ var XmtpService = class _XmtpService {
84281
84352
  (c) => c instanceof Group && c.id === groupId
84282
84353
  );
84283
84354
  if (!group) {
84284
- console.log(`[xmtp-sdk] allowGroup: groupId=${groupId} not found`);
84355
+ logWithTimestamp(`[xmtp-sdk] allowGroup: groupId=${groupId} not found`);
84285
84356
  logger.error(LogEvent.GROUP_CONSENT_UPDATE_FAILED, void 0, {
84286
84357
  ...agentExtras({
84287
84358
  walletAddress: myXmtpAddress,
@@ -84295,13 +84366,13 @@ var XmtpService = class _XmtpService {
84295
84366
  return false;
84296
84367
  }
84297
84368
  if (group.consentState === import_node_bindings2.ConsentState.Allowed) {
84298
- console.log(
84369
+ logWithTimestamp(
84299
84370
  `[xmtp-sdk] allowGroup: groupId=${groupId} already Allowed, skipping`
84300
84371
  );
84301
84372
  return true;
84302
84373
  }
84303
84374
  group.updateConsentState(import_node_bindings2.ConsentState.Allowed);
84304
- console.log(`[xmtp-sdk] allowGroup: groupId=${groupId} marked as Allowed`);
84375
+ logWithTimestamp(`[xmtp-sdk] allowGroup: groupId=${groupId} marked as Allowed`);
84305
84376
  logger.info(LogEvent.GROUP_CONSENT_CHANGED, {
84306
84377
  ...agentExtras({
84307
84378
  walletAddress: myXmtpAddress,
@@ -84313,7 +84384,7 @@ var XmtpService = class _XmtpService {
84313
84384
  });
84314
84385
  return true;
84315
84386
  } catch (err2) {
84316
- console.log(`[xmtp-sdk] allowGroup failed: groupId=${groupId}`, err2);
84387
+ logWithTimestamp(`[xmtp-sdk] allowGroup failed: groupId=${groupId}`, err2);
84317
84388
  logger.error(LogEvent.GROUP_CONSENT_UPDATE_FAILED, err2 instanceof Error ? err2 : new Error(String(err2)), {
84318
84389
  ...agentExtras({
84319
84390
  walletAddress: myXmtpAddress,
@@ -84330,14 +84401,14 @@ var XmtpService = class _XmtpService {
84330
84401
  const tag = `[xmtp-sdk:listUnknownGroups:${clientAddress}]`;
84331
84402
  const agent = this.getClientByAddress(clientAddress);
84332
84403
  if (!agent) {
84333
- console.log(`${tag} no client found, returning empty`);
84404
+ logWithTimestamp(`${tag} no client found, returning empty`);
84334
84405
  return [];
84335
84406
  }
84336
84407
  await agent.client.conversations.syncAll([import_node_bindings2.ConsentState.Unknown]);
84337
84408
  const groups = await agent.client.conversations.list({
84338
84409
  consentStates: [import_node_bindings2.ConsentState.Unknown]
84339
84410
  });
84340
- console.log(`${tag} Unknown groups: ${groups.length}`);
84411
+ logWithTimestamp(`${tag} Unknown groups: ${groups.length}`);
84341
84412
  const myInboxId = agent.client.inboxId;
84342
84413
  const myAgentId = this.getAgentByAddress(clientAddress)?.agentId ?? null;
84343
84414
  const result = [];
@@ -84381,7 +84452,7 @@ var XmtpService = class _XmtpService {
84381
84452
  messages: chatMsgs
84382
84453
  });
84383
84454
  } catch (err2) {
84384
- console.log(`${tag} failed to read group ${conv.id}:`, err2);
84455
+ logWithTimestamp(`${tag} failed to read group ${conv.id}:`, err2);
84385
84456
  logger.error(
84386
84457
  LogEvent.INBOUND_ROUTING_FAILED,
84387
84458
  err2 instanceof Error ? err2 : new Error(String(err2)),
@@ -84402,7 +84473,7 @@ var XmtpService = class _XmtpService {
84402
84473
  async denyGroup(myXmtpAddress, groupId) {
84403
84474
  const agent = this.getClientByAddress(myXmtpAddress);
84404
84475
  if (!agent) {
84405
- console.log(
84476
+ logWithTimestamp(
84406
84477
  `[xmtp-sdk] denyGroup: no client found for address=${myXmtpAddress}`
84407
84478
  );
84408
84479
  logger.error(LogEvent.GROUP_CONSENT_UPDATE_FAILED, void 0, {
@@ -84423,7 +84494,7 @@ var XmtpService = class _XmtpService {
84423
84494
  (c) => c instanceof Group && c.id === groupId
84424
84495
  );
84425
84496
  if (!group) {
84426
- console.log(`[xmtp-sdk] denyGroup: groupId=${groupId} not found`);
84497
+ logWithTimestamp(`[xmtp-sdk] denyGroup: groupId=${groupId} not found`);
84427
84498
  logger.error(LogEvent.GROUP_CONSENT_UPDATE_FAILED, void 0, {
84428
84499
  ...agentExtras({
84429
84500
  walletAddress: myXmtpAddress,
@@ -84437,7 +84508,7 @@ var XmtpService = class _XmtpService {
84437
84508
  return false;
84438
84509
  }
84439
84510
  group.updateConsentState(import_node_bindings2.ConsentState.Denied);
84440
- console.log(`[xmtp-sdk] denyGroup: groupId=${groupId} marked as Denied`);
84511
+ logWithTimestamp(`[xmtp-sdk] denyGroup: groupId=${groupId} marked as Denied`);
84441
84512
  logger.info(LogEvent.GROUP_CONSENT_CHANGED, {
84442
84513
  ...agentExtras({
84443
84514
  walletAddress: myXmtpAddress,
@@ -84449,7 +84520,7 @@ var XmtpService = class _XmtpService {
84449
84520
  });
84450
84521
  return true;
84451
84522
  } catch (err2) {
84452
- console.log(`[xmtp-sdk] denyGroup failed: groupId=${groupId}`, err2);
84523
+ logWithTimestamp(`[xmtp-sdk] denyGroup failed: groupId=${groupId}`, err2);
84453
84524
  logger.error(LogEvent.GROUP_CONSENT_UPDATE_FAILED, err2 instanceof Error ? err2 : new Error(String(err2)), {
84454
84525
  ...agentExtras({
84455
84526
  walletAddress: myXmtpAddress,
@@ -84481,9 +84552,9 @@ var XmtpService = class _XmtpService {
84481
84552
  import_node_bindings2.ConsentState.Allowed,
84482
84553
  import_node_bindings2.ConsentState.Unknown
84483
84554
  ]);
84484
- console.log(`${tag} conversations synced (non-Denied)`);
84555
+ logWithTimestamp(`${tag} conversations synced (non-Denied)`);
84485
84556
  } catch (err2) {
84486
- console.log(`${tag} conversation sync failed, skipping this client:`, err2);
84557
+ logWithTimestamp(`${tag} conversation sync failed, skipping this client:`, err2);
84487
84558
  logger.error(
84488
84559
  LogEvent.CONVERSATIONS_STREAM_FAILED,
84489
84560
  err2 instanceof Error ? err2 : void 0,
@@ -84491,8 +84562,8 @@ var XmtpService = class _XmtpService {
84491
84562
  );
84492
84563
  return;
84493
84564
  }
84494
- agent.use(selfFilterMiddleware());
84495
84565
  agent.use(loggingMiddleware(identity3));
84566
+ agent.use(selfFilterMiddleware());
84496
84567
  const inboundFactory = this.tools.createInboundMiddleware;
84497
84568
  if (inboundFactory) {
84498
84569
  agent.use(
@@ -84511,7 +84582,7 @@ var XmtpService = class _XmtpService {
84511
84582
  })
84512
84583
  );
84513
84584
  } else {
84514
- console.log(
84585
+ logWithTimestamp(
84515
84586
  `${tag} tools.createInboundMiddleware not injected \u2014 inbound routing disabled`
84516
84587
  );
84517
84588
  }
@@ -84519,7 +84590,7 @@ var XmtpService = class _XmtpService {
84519
84590
  const initialSyncMs = Date.now();
84520
84591
  this.syncByAddress.set(address, initialSyncMs);
84521
84592
  saveSyncForAddress(this.dataDir, address, initialSyncMs);
84522
- console.log(
84593
+ logWithTimestamp(
84523
84594
  `${tag} initialized sync timestamp at ${new Date(initialSyncMs).toISOString()}`
84524
84595
  );
84525
84596
  }
@@ -84527,13 +84598,13 @@ var XmtpService = class _XmtpService {
84527
84598
  const BASE_DELAY_MS = 1e3;
84528
84599
  const startWithRetry = async (attempt = 0) => {
84529
84600
  if (this.stoppedAddresses.has(address.toLowerCase()) || !this.clients.has(address)) {
84530
- console.log(`${tag} start skipped: client stopped or removed`);
84601
+ logWithTimestamp(`${tag} start skipped: client stopped or removed`);
84531
84602
  return;
84532
84603
  }
84533
84604
  try {
84534
84605
  await agent.start();
84535
84606
  } catch (err2) {
84536
- console.log(`${tag} agent.start error (attempt=${attempt}):`, err2);
84607
+ logWithTimestamp(`${tag} agent.start error (attempt=${attempt}):`, err2);
84537
84608
  logger.error(
84538
84609
  LogEvent.AGENT_START_FAILED,
84539
84610
  err2 instanceof Error ? err2 : void 0,
@@ -84547,24 +84618,24 @@ var XmtpService = class _XmtpService {
84547
84618
  };
84548
84619
  const scheduleRetry = (attempt) => {
84549
84620
  if (this.stoppedAddresses.has(address.toLowerCase()) || !this.clients.has(address)) {
84550
- console.log(`${tag} reconnect skipped: client stopped or removed`);
84621
+ logWithTimestamp(`${tag} reconnect skipped: client stopped or removed`);
84551
84622
  return;
84552
84623
  }
84553
84624
  if (attempt >= MAX_RETRIES) {
84554
- console.log(`${tag} reached max retries (${MAX_RETRIES}), giving up reconnect`);
84625
+ logWithTimestamp(`${tag} reached max retries (${MAX_RETRIES}), giving up reconnect`);
84555
84626
  return;
84556
84627
  }
84557
84628
  const delay = BASE_DELAY_MS * 2 ** attempt;
84558
- console.log(`${tag} reconnecting in ${delay}ms (attempt=${attempt + 1})`);
84629
+ logWithTimestamp(`${tag} reconnecting in ${delay}ms (attempt=${attempt + 1})`);
84559
84630
  setTimeout(() => void startWithRetry(attempt + 1), delay);
84560
84631
  };
84561
84632
  agent.on("error", (err2) => {
84562
- console.log(`${tag} agent stream error:`, err2);
84633
+ logWithTimestamp(`${tag} agent stream error:`, err2);
84563
84634
  logger.error(LogEvent.AGENT_STREAM_ERROR, err2, agentExtras(identity3));
84564
84635
  scheduleRetry(0);
84565
84636
  });
84566
84637
  void startWithRetry();
84567
- console.log(`${tag} message listener started`);
84638
+ logWithTimestamp(`${tag} message listener started`);
84568
84639
  });
84569
84640
  }
84570
84641
  async replayOfflineMessagesForAddress(address) {
@@ -84590,7 +84661,7 @@ var XmtpService = class _XmtpService {
84590
84661
  };
84591
84662
  const processOffline = this.tools.processOfflineMessage;
84592
84663
  if (!processOffline) {
84593
- console.log(
84664
+ logWithTimestamp(
84594
84665
  `${tag} tools.processOfflineMessage not injected \u2014 offline replay skipped`
84595
84666
  );
84596
84667
  summary.durationMs = Date.now() - addressReplayStartedAt;
@@ -84611,7 +84682,7 @@ var XmtpService = class _XmtpService {
84611
84682
  summary.listMs = Date.now() - listStartedAt;
84612
84683
  summary.conversations = conversations.length;
84613
84684
  } catch (err2) {
84614
- console.log(`${tag} conversation sync/list failed, skipping:`, err2);
84685
+ logWithTimestamp(`${tag} conversation sync/list failed, skipping:`, err2);
84615
84686
  logger.error(
84616
84687
  LogEvent.OFFLINE_REPLAY_FAILED,
84617
84688
  err2 instanceof Error ? err2 : void 0,
@@ -84697,7 +84768,7 @@ var XmtpService = class _XmtpService {
84697
84768
  const handleMs = Date.now() - handleStartedAt;
84698
84769
  summary.handleMs += handleMs;
84699
84770
  if (handled) {
84700
- console.log(
84771
+ logWithTimestamp(
84701
84772
  `${tag} replayed content=${preview}`
84702
84773
  );
84703
84774
  summary.replayed++;
@@ -84716,7 +84787,7 @@ var XmtpService = class _XmtpService {
84716
84787
  summary.skipped++;
84717
84788
  }
84718
84789
  } catch (err2) {
84719
- console.log(`${tag} replay handling failed: msgId=${msg.id}`, err2);
84790
+ logWithTimestamp(`${tag} replay handling failed: msgId=${msg.id}`, err2);
84720
84791
  logger.error(
84721
84792
  LogEvent.OFFLINE_REPLAY_MESSAGE_FAILED,
84722
84793
  err2 instanceof Error ? err2 : void 0,
@@ -84739,7 +84810,7 @@ var XmtpService = class _XmtpService {
84739
84810
  }
84740
84811
  }
84741
84812
  } catch (err2) {
84742
- console.log(`${tag} failed to read messages from conversation ${conv.id}:`, err2);
84813
+ logWithTimestamp(`${tag} failed to read messages from conversation ${conv.id}:`, err2);
84743
84814
  logger.error(
84744
84815
  LogEvent.OFFLINE_REPLAY_FAILED,
84745
84816
  err2 instanceof Error ? err2 : void 0,
@@ -84879,7 +84950,7 @@ async function resolve2() {
84879
84950
  }
84880
84951
  const envBin = process.env.ONCHAINOS_BIN;
84881
84952
  if (envBin) {
84882
- console.log(`[onchainos] using ONCHAINOS_BIN=${envBin}`);
84953
+ logWithTimestamp(`[onchainos] using ONCHAINOS_BIN=${envBin}`);
84883
84954
  resolvedBin = envBin;
84884
84955
  return resolvedBin;
84885
84956
  }
@@ -84888,17 +84959,17 @@ async function resolve2() {
84888
84959
  const { stdout } = await execFileAsync(shell, ["-lc", "command -v onchainos"]);
84889
84960
  const bin = extractExecutablePath(stdout);
84890
84961
  if (bin) {
84891
- console.log(`[onchainos] resolved binary via shell: ${bin}`);
84962
+ logWithTimestamp(`[onchainos] resolved binary via shell: ${bin}`);
84892
84963
  resolvedBin = bin;
84893
84964
  return resolvedBin;
84894
84965
  }
84895
84966
  } catch (err2) {
84896
- console.log(
84967
+ logWithTimestamp(
84897
84968
  "[onchainos] shell resolve failed, will fallback to bare 'onchainos':",
84898
84969
  err2
84899
84970
  );
84900
84971
  }
84901
- console.log(
84972
+ logWithTimestamp(
84902
84973
  "[onchainos] could not resolve binary path, falling back to bare 'onchainos'"
84903
84974
  );
84904
84975
  resolvedBin = "onchainos";
@@ -84948,16 +85019,16 @@ function commandForLog(bin, args) {
84948
85019
  async function exec(args) {
84949
85020
  const bin = await resolve2();
84950
85021
  const cmd = commandForLog(bin, args);
84951
- console.log(`[onchainos] exec: ${cmd}`);
85022
+ logWithTimestamp(`[onchainos] exec: ${cmd}`);
84952
85023
  const t0 = Date.now();
84953
85024
  try {
84954
85025
  const result = await execFileAsync(bin, args);
84955
- console.log(
85026
+ logWithTimestamp(
84956
85027
  `[onchainos] exec done: ${cmd} (${Date.now() - t0}ms, stdout=${result.stdout.length}B, stderr=${result.stderr.length}B)`
84957
85028
  );
84958
85029
  return result;
84959
85030
  } catch (err2) {
84960
- console.log(
85031
+ logWithTimestamp(
84961
85032
  `[onchainos] exec error: ${cmd} (${Date.now() - t0}ms) code=${err2.code} signal=${err2.signal} killed=${err2.killed} message=${err2.message}`
84962
85033
  );
84963
85034
  logger.error(
@@ -84985,21 +85056,7 @@ async function exec(args) {
84985
85056
  }
84986
85057
  }
84987
85058
 
84988
- // ../core/src/xmtp-sdk/onchainos/index.ts
84989
- function isAccountAgentGroup(item) {
84990
- return typeof item === "object" && item !== null && Array.isArray(item.agentList);
84991
- }
84992
- function normalizeAgentPage(raw) {
84993
- const list = [];
84994
- for (const item of raw.list) {
84995
- if (isAccountAgentGroup(item)) {
84996
- list.push(...item.agentList);
84997
- } else {
84998
- list.push(item);
84999
- }
85000
- }
85001
- return { list, page: raw.page, pageSize: raw.pageSize, total: raw.total };
85002
- }
85059
+ // ../core/src/xmtp-sdk/onchainos/cli-response.ts
85003
85060
  var CliErrorReason = {
85004
85061
  OK_FALSE: "ok_false",
85005
85062
  JSON_PARSE_FAILED: "json_parse_failed"
@@ -85047,6 +85104,8 @@ function parseCliJson(stdout, command, extras = {}) {
85047
85104
  throw parseErr;
85048
85105
  }
85049
85106
  }
85107
+
85108
+ // ../core/src/xmtp-sdk/onchainos/session-expired.ts
85050
85109
  var SESSION_EXPIRED_RE2 = /session expired/i;
85051
85110
  function isSessionExpired(stdout) {
85052
85111
  try {
@@ -85056,14 +85115,7 @@ function isSessionExpired(stdout) {
85056
85115
  return SESSION_EXPIRED_RE2.test(stdout);
85057
85116
  }
85058
85117
  }
85059
- var lastExpiredNotifyAt = 0;
85060
- var EXPIRED_NOTIFY_COOLDOWN_MS = 5 * 60 * 1e3;
85061
- function notifySessionExpired(command) {
85062
- const now = Date.now();
85063
- if (now - lastExpiredNotifyAt < EXPIRED_NOTIFY_COOLDOWN_MS) {
85064
- return;
85065
- }
85066
- lastExpiredNotifyAt = now;
85118
+ function reportSessionExpired(command) {
85067
85119
  logger.error(
85068
85120
  LogEvent.ONCHAINOS_SESSION_EXPIRED,
85069
85121
  new Error("onchainos session expired"),
@@ -85077,9 +85129,87 @@ function notifySessionExpired(command) {
85077
85129
  reason: "session_expired"
85078
85130
  }
85079
85131
  );
85132
+ }
85133
+
85134
+ // ../core/src/xmtp-sdk/onchainos/system-config.ts
85135
+ function notifyExpired(command, options) {
85136
+ if (options?.notifySessionExpired) {
85137
+ options.notifySessionExpired(command);
85138
+ return;
85139
+ }
85140
+ reportSessionExpired(command);
85141
+ }
85142
+ function guardSessionExpired(stdout, command, options) {
85143
+ if (isSessionExpired(stdout)) {
85144
+ notifyExpired(command, options);
85145
+ }
85146
+ }
85147
+ function guardCatchSessionExpired(err2, command, options) {
85148
+ const stdout = String(err2?.stdout ?? "");
85149
+ if (stdout && isSessionExpired(stdout)) {
85150
+ notifyExpired(command, options);
85151
+ }
85152
+ }
85153
+ async function fetchSystemConfig(options) {
85154
+ logWithTimestamp(`[onchainos] fetching system-config`);
85155
+ let stdout;
85156
+ let stderr;
85157
+ try {
85158
+ ({ stdout, stderr } = await exec(["agent", "system-config"]));
85159
+ } catch (err2) {
85160
+ guardCatchSessionExpired(err2, "system-config", options);
85161
+ throw err2;
85162
+ }
85163
+ if (stderr) {
85164
+ logWithTimestamp(`[onchainos] stderr (system-config): ${stderr}`);
85165
+ }
85166
+ const res = parseCliJson(
85167
+ stdout,
85168
+ "system-config"
85169
+ );
85170
+ if (!res.ok) {
85171
+ guardSessionExpired(stdout, "system-config", options);
85172
+ const parseErr = new Error(`onchainos agent system-config failed`);
85173
+ logger.error(
85174
+ LogEvent.ONCHAINOS_CLI_ERROR,
85175
+ parseErr,
85176
+ cliOkFalseExtras(stdout, "system-config")
85177
+ );
85178
+ throw parseErr;
85179
+ }
85180
+ logWithTimestamp(
85181
+ `[onchainos] fetched system-config: ${Object.keys(res.data).length} keys`
85182
+ );
85183
+ return res.data;
85184
+ }
85185
+
85186
+ // ../core/src/xmtp-sdk/onchainos/index.ts
85187
+ function isAccountAgentGroup(item) {
85188
+ return typeof item === "object" && item !== null && Array.isArray(item.agentList);
85189
+ }
85190
+ function normalizeAgentPage(raw) {
85191
+ const list = [];
85192
+ for (const item of raw.list) {
85193
+ if (isAccountAgentGroup(item)) {
85194
+ list.push(...item.agentList);
85195
+ } else {
85196
+ list.push(item);
85197
+ }
85198
+ }
85199
+ return { list, page: raw.page, pageSize: raw.pageSize, total: raw.total };
85200
+ }
85201
+ var lastExpiredNotifyAt = 0;
85202
+ var EXPIRED_NOTIFY_COOLDOWN_MS = 5 * 60 * 1e3;
85203
+ function notifySessionExpired(command) {
85204
+ const now = Date.now();
85205
+ if (now - lastExpiredNotifyAt < EXPIRED_NOTIFY_COOLDOWN_MS) {
85206
+ return;
85207
+ }
85208
+ lastExpiredNotifyAt = now;
85209
+ reportSessionExpired(command);
85080
85210
  const hook = XmtpService.getInstance().tools.notifySessionExpired;
85081
85211
  if (!hook) {
85082
- console.log(
85212
+ logWithTimestamp(
85083
85213
  "[onchainos] tools.notifySessionExpired not injected \u2014 skipping user notice"
85084
85214
  );
85085
85215
  return;
@@ -85087,15 +85217,15 @@ function notifySessionExpired(command) {
85087
85217
  try {
85088
85218
  hook(command);
85089
85219
  } catch (err2) {
85090
- console.log("[onchainos] tools.notifySessionExpired threw:", err2);
85220
+ logWithTimestamp("[onchainos] tools.notifySessionExpired threw:", err2);
85091
85221
  }
85092
85222
  }
85093
- function guardSessionExpired(stdout, command) {
85223
+ function guardSessionExpired2(stdout, command) {
85094
85224
  if (isSessionExpired(stdout)) {
85095
85225
  notifySessionExpired(command);
85096
85226
  }
85097
85227
  }
85098
- function guardCatchSessionExpired(err2, command) {
85228
+ function guardCatchSessionExpired2(err2, command) {
85099
85229
  const stdout = String(err2?.stdout ?? "");
85100
85230
  if (stdout && isSessionExpired(stdout)) {
85101
85231
  notifySessionExpired(command);
@@ -85152,7 +85282,7 @@ async function fetchAgentPage(page) {
85152
85282
  commandStatus: "rejected"
85153
85283
  });
85154
85284
  }
85155
- guardCatchSessionExpired(err2, "list-agents");
85285
+ guardCatchSessionExpired2(err2, "list-agents");
85156
85286
  throw err2;
85157
85287
  }
85158
85288
  logAgentListResponse({
@@ -85168,7 +85298,7 @@ async function fetchAgentPage(page) {
85168
85298
  { page: String(page), pageSize: String(PAGE_SIZE) }
85169
85299
  );
85170
85300
  if (!res.ok) {
85171
- guardSessionExpired(stdout, "list-agents");
85301
+ guardSessionExpired2(stdout, "list-agents");
85172
85302
  const parseErr = new Error("onchainos agent get failed");
85173
85303
  logger.error(
85174
85304
  LogEvent.ONCHAINOS_CLI_ERROR,
@@ -85187,7 +85317,7 @@ var ONCHAINOS_CHAIN_INDEX = "196";
85187
85317
  async function fetchAgentsByIds(agentIds) {
85188
85318
  const requested = [...new Set(agentIds.filter(Boolean))];
85189
85319
  if (requested.length > 0) {
85190
- console.log(
85320
+ logWithTimestamp(
85191
85321
  `[onchainos] executing: onchainos agent get --agent-ids ${requested.join(",")}`
85192
85322
  );
85193
85323
  let stdout;
@@ -85200,11 +85330,11 @@ async function fetchAgentsByIds(agentIds) {
85200
85330
  requested.join(",")
85201
85331
  ]));
85202
85332
  } catch (err2) {
85203
- guardCatchSessionExpired(err2, "get-agents-by-ids");
85333
+ guardCatchSessionExpired2(err2, "get-agents-by-ids");
85204
85334
  throw err2;
85205
85335
  }
85206
85336
  if (stderr) {
85207
- console.log(`[onchainos] stderr (get-agents-by-ids): ${stderr}`);
85337
+ logWithTimestamp(`[onchainos] stderr (get-agents-by-ids): ${stderr}`);
85208
85338
  }
85209
85339
  const res = parseCliJson(
85210
85340
  stdout,
@@ -85212,7 +85342,7 @@ async function fetchAgentsByIds(agentIds) {
85212
85342
  { agentIds: requested.join(",") }
85213
85343
  );
85214
85344
  if (!res.ok) {
85215
- guardSessionExpired(stdout, "get-agents-by-ids");
85345
+ guardSessionExpired2(stdout, "get-agents-by-ids");
85216
85346
  const parseErr = new Error("onchainos agent get --agent-ids failed");
85217
85347
  logger.error(
85218
85348
  LogEvent.ONCHAINOS_CLI_ERROR,
@@ -85237,7 +85367,7 @@ async function fetchAgentsByIds(agentIds) {
85237
85367
  return result;
85238
85368
  }
85239
85369
  async function fetchAgentByAddress(communicationAddress) {
85240
- console.log(
85370
+ logWithTimestamp(
85241
85371
  `[onchainos] executing: onchainos agent get-by-address --communication-address ${communicationAddress} --chain-index ${ONCHAINOS_CHAIN_INDEX}`
85242
85372
  );
85243
85373
  let stdout;
@@ -85252,11 +85382,11 @@ async function fetchAgentByAddress(communicationAddress) {
85252
85382
  ONCHAINOS_CHAIN_INDEX
85253
85383
  ]));
85254
85384
  } catch (err2) {
85255
- guardCatchSessionExpired(err2, "get-agent-by-address");
85385
+ guardCatchSessionExpired2(err2, "get-agent-by-address");
85256
85386
  throw err2;
85257
85387
  }
85258
85388
  if (stderr) {
85259
- console.log(`[onchainos] stderr (get-agent-by-address): ${stderr}`);
85389
+ logWithTimestamp(`[onchainos] stderr (get-agent-by-address): ${stderr}`);
85260
85390
  }
85261
85391
  const res = parseCliJson(
85262
85392
  stdout,
@@ -85264,7 +85394,7 @@ async function fetchAgentByAddress(communicationAddress) {
85264
85394
  { communicationAddress, chainIndex: ONCHAINOS_CHAIN_INDEX }
85265
85395
  );
85266
85396
  if (!res.ok) {
85267
- guardSessionExpired(stdout, "get-agent-by-address");
85397
+ guardSessionExpired2(stdout, "get-agent-by-address");
85268
85398
  const parseErr = new Error("onchainos agent get-by-address failed");
85269
85399
  logger.error(
85270
85400
  LogEvent.ONCHAINOS_CLI_ERROR,
@@ -85303,7 +85433,7 @@ async function listAllAgentsWithMetadata(previousFingerprint) {
85303
85433
  const changed = previousFingerprint === void 0 || previousFingerprint !== fingerprint;
85304
85434
  const stderrLines = stderrs.map(filterNoisyAgentIdentityLog).filter((line) => line.length > 0);
85305
85435
  for (const line of stderrLines) {
85306
- console.log(`[onchainos] stderr (${line})`);
85436
+ logWithTimestamp(`[onchainos] stderr (${line})`);
85307
85437
  }
85308
85438
  return {
85309
85439
  allAgents: agents,
@@ -85331,11 +85461,11 @@ function filterNoisyAgentIdentityLog(stderr) {
85331
85461
  }
85332
85462
  async function notifyAgentsWakeup(agentIds) {
85333
85463
  if (agentIds.length === 0) {
85334
- console.log("[onchainos] wakeup-notify: agentIds empty, skipping");
85464
+ logWithTimestamp("[onchainos] wakeup-notify: agentIds empty, skipping");
85335
85465
  return;
85336
85466
  }
85337
85467
  const ids = agentIds.join(",");
85338
- console.log(`[onchainos] sending wakeup-notify (agent-ids=${ids})`);
85468
+ logWithTimestamp(`[onchainos] sending wakeup-notify (agent-ids=${ids})`);
85339
85469
  try {
85340
85470
  const { stderr } = await exec([
85341
85471
  "agent",
@@ -85344,19 +85474,19 @@ async function notifyAgentsWakeup(agentIds) {
85344
85474
  ids
85345
85475
  ]);
85346
85476
  if (stderr) {
85347
- console.log(`[onchainos] stderr (wakeup-notify): ${stderr}`);
85477
+ logWithTimestamp(`[onchainos] stderr (wakeup-notify): ${stderr}`);
85348
85478
  }
85349
- console.log(`[onchainos] wakeup-notify succeeded (agent-ids=${ids})`);
85479
+ logWithTimestamp(`[onchainos] wakeup-notify succeeded (agent-ids=${ids})`);
85350
85480
  } catch (err2) {
85351
- guardCatchSessionExpired(err2, "wakeup-notify");
85352
- console.log(
85481
+ guardCatchSessionExpired2(err2, "wakeup-notify");
85482
+ logWithTimestamp(
85353
85483
  `[onchainos] wakeup-notify failed (agent-ids=${ids}):`,
85354
85484
  err2?.message ?? err2
85355
85485
  );
85356
85486
  }
85357
85487
  }
85358
85488
  async function sendHeartbeat(chainIndex) {
85359
- console.log(`[onchainos] sending heartbeat (chain-index=${chainIndex})`);
85489
+ logWithTimestamp(`[onchainos] sending heartbeat (chain-index=${chainIndex})`);
85360
85490
  try {
85361
85491
  const { stderr } = await exec([
85362
85492
  "agent",
@@ -85365,16 +85495,16 @@ async function sendHeartbeat(chainIndex) {
85365
85495
  chainIndex
85366
85496
  ]);
85367
85497
  if (stderr) {
85368
- console.log(`[onchainos] stderr (heartbeat): ${stderr}`);
85498
+ logWithTimestamp(`[onchainos] stderr (heartbeat): ${stderr}`);
85369
85499
  }
85370
- console.log(`[onchainos] heartbeat sent`);
85500
+ logWithTimestamp(`[onchainos] heartbeat sent`);
85371
85501
  } catch (err2) {
85372
- guardCatchSessionExpired(err2, "heartbeat");
85502
+ guardCatchSessionExpired2(err2, "heartbeat");
85373
85503
  throw err2;
85374
85504
  }
85375
85505
  }
85376
85506
  async function checkMessageEligible(params) {
85377
- console.log(
85507
+ logWithTimestamp(
85378
85508
  `[onchainos] checking message-eligible: job=${params.jobId} direction=${params.direction} providerSecurityRate=${params.providerSecurityRate}`
85379
85509
  );
85380
85510
  let stdout;
@@ -85403,11 +85533,11 @@ async function checkMessageEligible(params) {
85403
85533
  String(params.providerSecurityRate)
85404
85534
  ]));
85405
85535
  } catch (err2) {
85406
- guardCatchSessionExpired(err2, "message-eligible");
85536
+ guardCatchSessionExpired2(err2, "message-eligible");
85407
85537
  throw new Error("message-eligible-cli-error", { cause: err2 });
85408
85538
  }
85409
85539
  if (stderr) {
85410
- console.log(`[onchainos] stderr (message-eligible): ${stderr}`);
85540
+ logWithTimestamp(`[onchainos] stderr (message-eligible): ${stderr}`);
85411
85541
  }
85412
85542
  let res;
85413
85543
  try {
@@ -85426,8 +85556,8 @@ async function checkMessageEligible(params) {
85426
85556
  throw new Error("message-eligible-json-parse-failed", { cause: err2 });
85427
85557
  }
85428
85558
  if (!res.ok) {
85429
- guardSessionExpired(stdout, "message-eligible");
85430
- console.warn(
85559
+ guardSessionExpired2(stdout, "message-eligible");
85560
+ warnWithTimestamp(
85431
85561
  `[onchainos] message-eligible ok=false: ${stdout.slice(0, 200)}`
85432
85562
  );
85433
85563
  logger.error(
@@ -85449,62 +85579,30 @@ async function checkMessageEligible(params) {
85449
85579
  );
85450
85580
  throw new Error("message-eligible-ok-false");
85451
85581
  }
85452
- console.log(
85582
+ logWithTimestamp(
85453
85583
  `[onchainos] message-eligible result: eligible=${res.data.eligible}`
85454
85584
  );
85455
85585
  return res.data;
85456
85586
  }
85457
- async function fetchSystemConfig() {
85458
- console.log(`[onchainos] fetching system-config`);
85459
- let stdout;
85460
- let stderr;
85461
- try {
85462
- ({ stdout, stderr } = await exec(["agent", "system-config"]));
85463
- } catch (err2) {
85464
- guardCatchSessionExpired(err2, "system-config");
85465
- throw err2;
85466
- }
85467
- if (stderr) {
85468
- console.log(`[onchainos] stderr (system-config): ${stderr}`);
85469
- }
85470
- const res = parseCliJson(
85471
- stdout,
85472
- "system-config"
85473
- );
85474
- if (!res.ok) {
85475
- guardSessionExpired(stdout, "system-config");
85476
- const parseErr = new Error(`onchainos agent system-config failed`);
85477
- logger.error(
85478
- LogEvent.ONCHAINOS_CLI_ERROR,
85479
- parseErr,
85480
- cliOkFalseExtras(stdout, "system-config")
85481
- );
85482
- throw parseErr;
85483
- }
85484
- console.log(
85485
- `[onchainos] fetched system-config: ${Object.keys(res.data).length} keys`
85486
- );
85487
- return res.data;
85488
- }
85489
85587
  async function fetchSensitiveWords() {
85490
- console.log(`[onchainos] fetching sensitive words`);
85588
+ logWithTimestamp(`[onchainos] fetching sensitive words`);
85491
85589
  let stdout;
85492
85590
  let stderr;
85493
85591
  try {
85494
85592
  ({ stdout, stderr } = await exec(["agent", "sensitive-words"]));
85495
85593
  } catch (err2) {
85496
- guardCatchSessionExpired(err2, "sensitive-words");
85594
+ guardCatchSessionExpired2(err2, "sensitive-words");
85497
85595
  throw err2;
85498
85596
  }
85499
85597
  if (stderr) {
85500
- console.log(`[onchainos] stderr (sensitive-words): ${stderr}`);
85598
+ logWithTimestamp(`[onchainos] stderr (sensitive-words): ${stderr}`);
85501
85599
  }
85502
85600
  const res = parseCliJson(
85503
85601
  stdout,
85504
85602
  "sensitive-words"
85505
85603
  );
85506
85604
  if (!res.ok) {
85507
- guardSessionExpired(stdout, "sensitive-words");
85605
+ guardSessionExpired2(stdout, "sensitive-words");
85508
85606
  const parseErr = new Error(`onchainos agent sensitive-words failed`);
85509
85607
  logger.error(
85510
85608
  LogEvent.ONCHAINOS_CLI_ERROR,
@@ -85522,7 +85620,7 @@ async function fetchSensitiveWords() {
85522
85620
  }
85523
85621
  }
85524
85622
  const result = [...words];
85525
- console.log(
85623
+ logWithTimestamp(
85526
85624
  `[onchainos] fetched ${res.data.length} sensitive word entries \u2192 ${result.length} unique words`
85527
85625
  );
85528
85626
  return result;
@@ -85640,7 +85738,7 @@ function setOpenClawWebSocketFactoryForTests(factory) {
85640
85738
  }
85641
85739
  function clearClient() {
85642
85740
  if (sharedClient) {
85643
- console.error(`${LOG_PREFIX} clear client`);
85741
+ errorWithTimestamp(`${LOG_PREFIX} clear client`);
85644
85742
  sharedClient.close();
85645
85743
  }
85646
85744
  sharedClient = null;
@@ -85668,7 +85766,7 @@ async function ensureClient(timeoutMs) {
85668
85766
  const elapsedMs = Date.now() - startedAt;
85669
85767
  const remainingMs = Math.max(1, timeoutMs - elapsedMs);
85670
85768
  const fallbackProtocol = firstProtocol === PREFERRED_PROTOCOL_VERSION ? LEGACY_PROTOCOL_VERSION : PREFERRED_PROTOCOL_VERSION;
85671
- console.error(
85769
+ errorWithTimestamp(
85672
85770
  `${LOG_PREFIX} protocol fallback from=${firstProtocol} to=${fallbackProtocol} remainingMs=${remainingMs}: ${formatErrorMessage(err2)}`
85673
85771
  );
85674
85772
  const fallbackClient = new MinimalGatewayClient(config, fallbackProtocol);
@@ -85680,7 +85778,7 @@ async function ensureClient(timeoutMs) {
85680
85778
  }
85681
85779
  function stopOpenClawGateway() {
85682
85780
  if (!sharedClient) {
85683
- console.error(`${LOG_PREFIX} stop requested with no active client`);
85781
+ errorWithTimestamp(`${LOG_PREFIX} stop requested with no active client`);
85684
85782
  return;
85685
85783
  }
85686
85784
  clearClient();
@@ -85688,12 +85786,12 @@ function stopOpenClawGateway() {
85688
85786
  async function callOpenClawGateway(opts) {
85689
85787
  const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
85690
85788
  const startedAt = Date.now();
85691
- console.error(`${LOG_PREFIX} rpc start method=${opts.method} timeoutMs=${timeoutMs}`);
85789
+ errorWithTimestamp(`${LOG_PREFIX} rpc start method=${opts.method} timeoutMs=${timeoutMs}`);
85692
85790
  for (let attempt = 0; ; attempt += 1) {
85693
85791
  try {
85694
85792
  const client = await ensureClient(timeoutMs);
85695
85793
  const result = await client.request(opts.method, opts.params, { timeoutMs });
85696
- console.error(`${LOG_PREFIX} rpc ok method=${opts.method} durationMs=${Date.now() - startedAt} attempts=${attempt + 1}`);
85794
+ errorWithTimestamp(`${LOG_PREFIX} rpc ok method=${opts.method} durationMs=${Date.now() - startedAt} attempts=${attempt + 1}`);
85697
85795
  return result;
85698
85796
  } catch (err2) {
85699
85797
  const message = err2 instanceof Error ? err2.message : String(err2);
@@ -85702,13 +85800,13 @@ async function callOpenClawGateway(opts) {
85702
85800
  clearClient();
85703
85801
  }
85704
85802
  if (isGatewayStartingError(err2) && delayMs !== void 0 && Date.now() + delayMs - startedAt < timeoutMs) {
85705
- console.error(
85803
+ errorWithTimestamp(
85706
85804
  `${LOG_PREFIX} rpc retry method=${opts.method} attempt=${attempt + 1} delayMs=${delayMs}: ${message}`
85707
85805
  );
85708
85806
  await sleep(delayMs);
85709
85807
  continue;
85710
85808
  }
85711
- console.error(
85809
+ errorWithTimestamp(
85712
85810
  `${LOG_PREFIX} rpc failed method=${opts.method} durationMs=${Date.now() - startedAt} attempts=${attempt + 1}: ${message}`
85713
85811
  );
85714
85812
  if (isGatewayStartingError(err2)) {
@@ -85804,7 +85902,7 @@ var MinimalGatewayClient = class {
85804
85902
  return this.ready && !this.closed && this.ws?.readyState === 1;
85805
85903
  }
85806
85904
  async connect(timeoutMs) {
85807
- console.error(
85905
+ errorWithTimestamp(
85808
85906
  `${LOG_PREFIX} connect url=${this.config.url} source=${this.config.source} instanceId=${this.instanceId} protocol=${this.protocolVersion} passwordConfigured=${!!this.config.password} tokenConfigured=${!!this.config.token} scopes=${DEFAULT_SCOPES.join(",")}`
85809
85907
  );
85810
85908
  const ws = wsFactory(this.config.url);
@@ -85861,7 +85959,7 @@ var MinimalGatewayClient = class {
85861
85959
  }
85862
85960
  });
85863
85961
  });
85864
- console.error(`${LOG_PREFIX} hello ok instanceId=${this.instanceId} protocol=${this.protocolVersion}`);
85962
+ errorWithTimestamp(`${LOG_PREFIX} hello ok instanceId=${this.instanceId} protocol=${this.protocolVersion}`);
85865
85963
  }
85866
85964
  request(method, params, options = {}) {
85867
85965
  if (method === "connect") {
@@ -85937,7 +86035,7 @@ var MinimalGatewayClient = class {
85937
86035
  try {
85938
86036
  frame = JSON.parse(String(raw));
85939
86037
  } catch (err2) {
85940
- console.error(`${LOG_PREFIX} invalid frame: ${err2 instanceof Error ? err2.message : String(err2)}`);
86038
+ errorWithTimestamp(`${LOG_PREFIX} invalid frame: ${err2 instanceof Error ? err2.message : String(err2)}`);
85941
86039
  return;
85942
86040
  }
85943
86041
  if (frame.type !== "res") {
@@ -85959,7 +86057,7 @@ var MinimalGatewayClient = class {
85959
86057
  pending.reject(toGatewayError(frame.error));
85960
86058
  }
85961
86059
  handleClose(code2, reason) {
85962
- console.error(`${LOG_PREFIX} closed instanceId=${this.instanceId} code=${code2 ?? 0} reason=${reason || "no reason"}`);
86060
+ errorWithTimestamp(`${LOG_PREFIX} closed instanceId=${this.instanceId} code=${code2 ?? 0} reason=${reason || "no reason"}`);
85963
86061
  this.ready = false;
85964
86062
  for (const [id, pending] of this.pending) {
85965
86063
  clearTimeout(pending.timer);
@@ -85983,7 +86081,7 @@ function readSyncedGatewayConfig(env) {
85983
86081
  token: synced.token
85984
86082
  };
85985
86083
  } catch (err2) {
85986
- console.error(`${LOG_PREFIX} failed to read synced gateway config: ${err2 instanceof Error ? err2.message : String(err2)}`);
86084
+ errorWithTimestamp(`${LOG_PREFIX} failed to read synced gateway config: ${err2 instanceof Error ? err2.message : String(err2)}`);
85987
86085
  return null;
85988
86086
  }
85989
86087
  }
@@ -85994,7 +86092,7 @@ function buildConnectParams(config, instanceId, protocolVersion) {
85994
86092
  client: {
85995
86093
  id: "gateway-client",
85996
86094
  displayName: "okx-a2a-node",
85997
- version: "0.0.13-beta-d0ec14bc63-260622192924",
86095
+ version: "0.0.13",
85998
86096
  platform: "node",
85999
86097
  mode: "backend",
86000
86098
  instanceId
@@ -86005,7 +86103,7 @@ function buildConnectParams(config, instanceId, protocolVersion) {
86005
86103
  commands: [],
86006
86104
  permissions: {},
86007
86105
  locale: Intl.DateTimeFormat().resolvedOptions().locale || "en-US",
86008
- userAgent: `okx-a2a-node/${"0.0.13-beta-d0ec14bc63-260622192924"}`,
86106
+ userAgent: `okx-a2a-node/${"0.0.13"}`,
86009
86107
  auth: {
86010
86108
  ...config.token ? { token: config.token } : {},
86011
86109
  ...config.password ? { password: config.password } : {}
@@ -86130,313 +86228,6 @@ function safeDecode(value) {
86130
86228
  }
86131
86229
  }
86132
86230
 
86133
- // src/openclaw-route.ts
86134
- var import_node_fs13 = require("node:fs");
86135
- var import_node_os5 = require("node:os");
86136
- var import_node_path17 = require("node:path");
86137
- var OPENCLAW_GATEWAY_ROUTE_GROUP_ID = "__openclaw_gateway_route__";
86138
- var CURRENT_GATEWAY_SESSION_KEYS_ENV = "OKX_A2A_CURRENT_GATEWAY_SESSION_KEYS";
86139
- var NON_DELIVERY_CHANNELS = /* @__PURE__ */ new Set(["heartbeat", "cron", "webhook", "voice"]);
86140
- var ACTIVE_ORIGIN_TTL_MS = 30 * 6e4;
86141
- function currentOpenClawGatewaySessionKey(env = process.env) {
86142
- for (const candidate of currentOpenClawGatewaySessionCandidates(env)) {
86143
- if (candidate.ok) {
86144
- return candidate.sessionKey;
86145
- }
86146
- }
86147
- return null;
86148
- }
86149
- function bindOpenClawGatewayRouteFromEnv(store, input, env = process.env) {
86150
- const jobId = normalizeText(input.jobId);
86151
- if (!jobId) {
86152
- return null;
86153
- }
86154
- let routes = readOpenClawRouteEntries(store, jobId);
86155
- let firstBound = null;
86156
- for (const candidate of currentOpenClawGatewaySessionCandidates(env, input.gatewaySessionKeys)) {
86157
- if (!candidate.ok) {
86158
- logOpenClawRouteSkip(candidate.reason, {
86159
- jobId,
86160
- sessionKey: candidate.sessionKey,
86161
- existingRoute: resolveOpenClawGatewayRoute(store, { jobId })
86162
- });
86163
- continue;
86164
- }
86165
- const channel = channelFromOpenClawGatewaySessionKey(candidate.sessionKey);
86166
- if (!channel) {
86167
- logOpenClawRouteSkip("invalid_gateway_session_key", {
86168
- jobId,
86169
- sessionKey: candidate.sessionKey,
86170
- existingRoute: resolveOpenClawGatewayRoute(store, { jobId })
86171
- });
86172
- continue;
86173
- }
86174
- const existingRoute = routes.find((route2) => route2.platform === channel) ?? null;
86175
- const route = existingRoute ?? buildOpenClawRouteEntry(candidate.sessionKey, channel);
86176
- routes = persistOpenClawRouteBinding(routes, route);
86177
- firstBound ??= route.sessionKey;
86178
- }
86179
- if (firstBound) {
86180
- const binding = store.setJobProviderGatewayRoutes({ jobId, provider: "openclaw", routes });
86181
- if (binding.provider !== "openclaw") {
86182
- return null;
86183
- }
86184
- return firstBound;
86185
- }
86186
- return resolveOpenClawGatewayRoute(store, { jobId })?.sessionKey ?? null;
86187
- }
86188
- function currentOpenClawGatewaySessionCandidates(env = process.env, explicitSessionKeys) {
86189
- const platform = normalizeText(env.OKX_A2A_CURRENT_GATEWAY_PLATFORM);
86190
- const chatId = normalizeText(env.OKX_A2A_CURRENT_GATEWAY_CHAT_ID);
86191
- const threadId = normalizeText(env.OKX_A2A_CURRENT_GATEWAY_THREAD_ID);
86192
- const rawKeys = [
86193
- ...Array.isArray(explicitSessionKeys) ? explicitSessionKeys : [],
86194
- ...readGatewaySessionKeysEnv(env),
86195
- normalizeText(env.OKX_A2A_CURRENT_GATEWAY_SESSION_KEY),
86196
- platform && chatId ? deriveOpenClawGatewaySessionKey({ platform, chatId, threadId }) : null,
86197
- normalizeText(env.OKX_A2A_CURRENT_SESSION_KEY),
86198
- ...readSingleActiveOriginSessionKey(env)
86199
- ];
86200
- const seen = /* @__PURE__ */ new Set();
86201
- const candidates = [];
86202
- for (const key of rawKeys) {
86203
- const normalized = normalizeText(key);
86204
- if (!normalized || seen.has(normalized)) {
86205
- continue;
86206
- }
86207
- seen.add(normalized);
86208
- candidates.push(validateOpenClawGatewaySessionKey(normalized));
86209
- }
86210
- if (candidates.length > 0) {
86211
- return candidates;
86212
- }
86213
- return [{ ok: false, reason: "missing_gateway_session_key" }];
86214
- }
86215
- function resolveOpenClawGatewayRoute(store, input) {
86216
- return resolveOpenClawGatewayRoutes(store, input)[0] ?? null;
86217
- }
86218
- function resolveOpenClawGatewayRoutes(store, input) {
86219
- const jobId = normalizeText(input.jobId) ?? inferJobIdFromSessionKey2(normalizeText(input.sessionKey));
86220
- if (jobId) {
86221
- return readOpenClawRouteEntries(store, jobId).map((route) => toOpenClawGatewayRoute(route, jobId));
86222
- }
86223
- return [];
86224
- }
86225
- function isValidOpenClawGatewaySessionKey(sessionKey) {
86226
- return validateOpenClawGatewaySessionKey(sessionKey).ok;
86227
- }
86228
- function buildOpenClawRouteEntry(sessionKey, channel) {
86229
- const parsed = parseOpenClawGatewaySessionKey(sessionKey);
86230
- return {
86231
- platform: channel,
86232
- sessionKey,
86233
- gatewaySessionKey: sessionKey,
86234
- ...parsed.chatId ? { chatId: parsed.chatId } : {},
86235
- ...parsed.threadId ? { threadId: parsed.threadId } : {},
86236
- updatedAt: (/* @__PURE__ */ new Date()).toISOString()
86237
- };
86238
- }
86239
- function persistOpenClawRouteBinding(routes, route) {
86240
- const nextRoute = {
86241
- ...route,
86242
- updatedAt: (/* @__PURE__ */ new Date()).toISOString()
86243
- };
86244
- if (routes.some((existing) => existing.platform === nextRoute.platform)) {
86245
- return routes;
86246
- }
86247
- return [...routes, nextRoute];
86248
- }
86249
- function toOpenClawGatewayRoute(route, jobId) {
86250
- const sessionKey = route.gatewaySessionKey || route.sessionKey;
86251
- return {
86252
- sessionKey,
86253
- jobId,
86254
- routeSessionKey: route.sessionKey,
86255
- updatedAt: route.updatedAt ?? "",
86256
- channel: route.platform
86257
- };
86258
- }
86259
- function readOpenClawRouteEntries(store, jobId) {
86260
- const binding = store?.getJobProviderBinding(jobId);
86261
- if (binding?.provider !== "openclaw") {
86262
- return [];
86263
- }
86264
- const routes = binding.gatewayRoutes ?? [];
86265
- const seenChannels = /* @__PURE__ */ new Set();
86266
- const validRoutes = [];
86267
- for (const route of routes) {
86268
- const sessionKey = normalizeText(route.gatewaySessionKey) ?? normalizeText(route.sessionKey);
86269
- const channel = channelFromOpenClawGatewaySessionKey(sessionKey);
86270
- if (!sessionKey || !channel || seenChannels.has(channel)) {
86271
- continue;
86272
- }
86273
- seenChannels.add(channel);
86274
- validRoutes.push({
86275
- platform: channel,
86276
- sessionKey: route.sessionKey,
86277
- gatewaySessionKey: sessionKey,
86278
- ...route.chatId ? { chatId: route.chatId } : {},
86279
- ...route.threadId ? { threadId: route.threadId } : {},
86280
- ...route.updatedAt ? { updatedAt: route.updatedAt } : {}
86281
- });
86282
- }
86283
- return validRoutes;
86284
- }
86285
- function parseOpenClawGatewaySessionKey(sessionKey) {
86286
- const parts = sessionKey.split(":");
86287
- if (parts.length < 4 || parts[0] !== "agent") {
86288
- return {};
86289
- }
86290
- const platform = parts[2];
86291
- const targetKind = parts[3];
86292
- if (platform === "discord" && targetKind === "thread") {
86293
- return {
86294
- ...parts[4] ? { chatId: parts[4] } : {},
86295
- ...parts[5] ? { threadId: parts[5] } : {}
86296
- };
86297
- }
86298
- if (platform === "discord" && targetKind === "channel") {
86299
- return parts[4] ? { chatId: parts[4] } : {};
86300
- }
86301
- if (platform === "discord" && targetKind === "dm") {
86302
- return parts[4] ? { chatId: parts[4] } : {};
86303
- }
86304
- if (platform === "telegram" && targetKind === "direct") {
86305
- return parts[4] ? { chatId: parts[4] } : {};
86306
- }
86307
- if (platform === "telegram" && targetKind === "group") {
86308
- return {
86309
- ...parts[4] ? { chatId: parts[4] } : {},
86310
- ...parts[6] ? { threadId: parts[6] } : {}
86311
- };
86312
- }
86313
- return {};
86314
- }
86315
- function validateOpenClawGatewaySessionKey(sessionKey) {
86316
- const key = normalizeText(sessionKey);
86317
- if (!key) {
86318
- return { ok: false, reason: "missing_gateway_session_key" };
86319
- }
86320
- if (key.startsWith("backup:")) {
86321
- return { ok: false, reason: "internal_gateway_session_key", sessionKey: key };
86322
- }
86323
- if (key === "agent:main") {
86324
- return { ok: true, sessionKey: key };
86325
- }
86326
- const parts = key.split(":");
86327
- if (parts.length < 4 || parts[0] !== "agent" || !parts[1]) {
86328
- return { ok: false, reason: "invalid_gateway_session_key", sessionKey: key };
86329
- }
86330
- const platform = parts[2];
86331
- if (!platform || platform === "okx-a2a" || NON_DELIVERY_CHANNELS.has(platform)) {
86332
- return { ok: false, reason: "internal_gateway_session_key", sessionKey: key };
86333
- }
86334
- return { ok: true, sessionKey: key };
86335
- }
86336
- function channelFromOpenClawGatewaySessionKey(sessionKey) {
86337
- const key = normalizeText(sessionKey);
86338
- if (!key) {
86339
- return null;
86340
- }
86341
- if (key === "agent:main") {
86342
- return "main";
86343
- }
86344
- const validation = validateOpenClawGatewaySessionKey(key);
86345
- if (!validation.ok) {
86346
- return null;
86347
- }
86348
- return key.split(":")[2] ?? null;
86349
- }
86350
- function deriveOpenClawGatewaySessionKey(input) {
86351
- const chatId = encodeURIComponent(input.chatId);
86352
- const threadId = input.threadId ? encodeURIComponent(input.threadId) : "";
86353
- if (input.platform === "telegram") {
86354
- return threadId ? `agent:main:telegram:group:${chatId}:topic:${threadId}` : `agent:main:telegram:direct:${chatId}`;
86355
- }
86356
- return threadId ? `agent:main:${input.platform}:thread:${chatId}:${threadId}` : `agent:main:${input.platform}:dm:${chatId}`;
86357
- }
86358
- function readGatewaySessionKeysEnv(env) {
86359
- const raw = normalizeText(env[CURRENT_GATEWAY_SESSION_KEYS_ENV]);
86360
- if (!raw) {
86361
- return [];
86362
- }
86363
- try {
86364
- const parsed = JSON.parse(raw);
86365
- if (Array.isArray(parsed)) {
86366
- return parsed.filter((item) => typeof item === "string" && item.trim().length > 0);
86367
- }
86368
- } catch {
86369
- }
86370
- return raw.split(",").map((item) => item.trim()).filter(Boolean);
86371
- }
86372
- function readSingleActiveOriginSessionKey(env) {
86373
- const path = (0, import_node_path17.join)(resolveTaskHome2(env), "run", "gateway-route-origins.json");
86374
- if (!(0, import_node_fs13.existsSync)(path)) {
86375
- return [];
86376
- }
86377
- try {
86378
- const parsed = JSON.parse((0, import_node_fs13.readFileSync)(path, "utf8"));
86379
- if (!isRecord2(parsed) || !Array.isArray(parsed.origins)) {
86380
- return [];
86381
- }
86382
- const now = Date.now();
86383
- const valid = parsed.origins.filter((item) => isRecord2(item)).map((item) => ({
86384
- sessionKey: normalizeText(typeof item.sessionKey === "string" ? item.sessionKey : null),
86385
- count: typeof item.count === "number" && Number.isFinite(item.count) ? item.count : 0,
86386
- updatedAt: typeof item.updatedAt === "number" && Number.isFinite(item.updatedAt) ? item.updatedAt : 0
86387
- })).filter((item) => item.sessionKey && item.count > 0 && now - item.updatedAt <= ACTIVE_ORIGIN_TTL_MS && validateOpenClawGatewaySessionKey(item.sessionKey).ok);
86388
- const sessionKeys = [...new Set(valid.map((item) => item.sessionKey).filter(Boolean))];
86389
- return sessionKeys.length === 1 ? sessionKeys : [];
86390
- } catch (err2) {
86391
- console.error(
86392
- `[openclaw-route] failed to read active gateway route origin state: ${err2 instanceof Error ? err2.message : String(err2)}`
86393
- );
86394
- return [];
86395
- }
86396
- }
86397
- function resolveTaskHome2(env) {
86398
- return env.OKX_AGENT_TASK_HOME?.trim() || (0, import_node_path17.join)((0, import_node_os5.homedir)(), ".okx-agent-task");
86399
- }
86400
- function logOpenClawRouteSkip(reason, input) {
86401
- if (reason === "missing_gateway_session_key") {
86402
- return;
86403
- }
86404
- console.error(
86405
- `[openclaw-route] skipped gateway route bind reason=${reason} jobId=${input.jobId} sessionKey=${input.sessionKey ?? "(none)"} existingRoute=${input.existingRoute?.sessionKey ?? "(none)"}`
86406
- );
86407
- }
86408
- function inferJobIdFromSessionKey2(sessionKey) {
86409
- if (!sessionKey) {
86410
- return null;
86411
- }
86412
- const parts = sessionKey.split(":");
86413
- if (parts.length >= 2 && parts[0] === "job") {
86414
- return safeDecode2(parts[1]);
86415
- }
86416
- if (sessionKey.startsWith("backup:")) {
86417
- return safeDecode2(sessionKey.slice("backup:".length));
86418
- }
86419
- const gatewayJob = /(?:^|[?&:])job=([^:&]+)/.exec(sessionKey);
86420
- if (gatewayJob?.[1]) {
86421
- return safeDecode2(gatewayJob[1]);
86422
- }
86423
- return null;
86424
- }
86425
- function normalizeText(value) {
86426
- const text = value?.trim();
86427
- return text ? text : null;
86428
- }
86429
- function isRecord2(value) {
86430
- return typeof value === "object" && value !== null && !Array.isArray(value);
86431
- }
86432
- function safeDecode2(value) {
86433
- try {
86434
- return decodeURIComponent(value);
86435
- } catch {
86436
- return value;
86437
- }
86438
- }
86439
-
86440
86231
  // src/outbound-behavior.ts
86441
86232
  var SqliteOutboundBehavior = class {
86442
86233
  provider;
@@ -86524,7 +86315,7 @@ function assertLatestUserFanoutDelivered(operation, payload) {
86524
86315
  const result = payload;
86525
86316
  const dispatched = Array.isArray(result.dispatched) ? result.dispatched.length : null;
86526
86317
  const failed = Array.isArray(result.failed) ? result.failed.length : null;
86527
- if (dispatched === 0 || result.ok === false && dispatched === null) {
86318
+ if (result.ok === false || dispatched === 0) {
86528
86319
  throw Object.assign(
86529
86320
  new Error(
86530
86321
  `${operation} did not deliver to any OpenClaw user session (dispatched=${dispatched ?? "unknown"} failed=${failed ?? "unknown"})`
@@ -86545,10 +86336,10 @@ var GatewayOutboundBehavior = class {
86545
86336
  }
86546
86337
  async createSession(input) {
86547
86338
  const gatewaySessionKey = this.resolveGatewaySessionKey(input);
86548
- console.error(`${GATEWAY_OUTBOUND_LOG_PREFIX} createSession sessionKey=${input.sessionKey} gatewaySessionKey=${gatewaySessionKey}`);
86339
+ errorWithTimestamp(`${GATEWAY_OUTBOUND_LOG_PREFIX} createSession sessionKey=${input.sessionKey} gatewaySessionKey=${gatewaySessionKey}`);
86549
86340
  try {
86550
86341
  await this.gateway.callSessionsCreate({ key: gatewaySessionKey });
86551
- console.error(`${GATEWAY_OUTBOUND_LOG_PREFIX} createSession ok sessionKey=${input.sessionKey} gatewaySessionKey=${gatewaySessionKey}`);
86342
+ errorWithTimestamp(`${GATEWAY_OUTBOUND_LOG_PREFIX} createSession ok sessionKey=${input.sessionKey} gatewaySessionKey=${gatewaySessionKey}`);
86552
86343
  logger.info(LogEvent.SESSION_CREATED, gatewayOutboundExtra("sessions.create", {
86553
86344
  sessionKey: input.sessionKey,
86554
86345
  gatewaySessionKey,
@@ -86566,7 +86357,7 @@ var GatewayOutboundBehavior = class {
86566
86357
  async deleteSession(input) {
86567
86358
  const stored = this.sessionMetaStore?.getSession(input.sessionKey);
86568
86359
  const gatewaySessionKey = this.resolveGatewaySessionKey(input);
86569
- console.error(`${GATEWAY_OUTBOUND_LOG_PREFIX} deleteSession sessionKey=${input.sessionKey} gatewaySessionKey=${gatewaySessionKey}`);
86360
+ errorWithTimestamp(`${GATEWAY_OUTBOUND_LOG_PREFIX} deleteSession sessionKey=${input.sessionKey} gatewaySessionKey=${gatewaySessionKey}`);
86570
86361
  try {
86571
86362
  const result = await this.gateway.callDeleteSessions({
86572
86363
  sessionKey: input.sessionKey,
@@ -86574,7 +86365,7 @@ var GatewayOutboundBehavior = class {
86574
86365
  ...stored?.myAgentId ? { myAgentId: stored.myAgentId } : {},
86575
86366
  ...stored?.toAgentId ? { toAgentId: stored.toAgentId } : {}
86576
86367
  });
86577
- console.error(`${GATEWAY_OUTBOUND_LOG_PREFIX} deleteSession ok sessionKey=${input.sessionKey} gatewaySessionKey=${gatewaySessionKey} deleted=${result.deleted ?? "(unknown)"}`);
86368
+ errorWithTimestamp(`${GATEWAY_OUTBOUND_LOG_PREFIX} deleteSession ok sessionKey=${input.sessionKey} gatewaySessionKey=${gatewaySessionKey} deleted=${result.deleted ?? "(unknown)"}`);
86578
86369
  logger.info(LogEvent.SESSION_DELETED, gatewayOutboundExtra("okx-a2a.delete_sessions", {
86579
86370
  sessionKey: input.sessionKey,
86580
86371
  gatewaySessionKey,
@@ -86590,7 +86381,7 @@ var GatewayOutboundBehavior = class {
86590
86381
  }
86591
86382
  async dispatchSessionMessage(input) {
86592
86383
  const gatewaySessionKey = this.resolveGatewaySessionKey(input);
86593
- console.error(
86384
+ errorWithTimestamp(
86594
86385
  `${GATEWAY_OUTBOUND_LOG_PREFIX} dispatchSessionMessage sessionKey=${input.sessionKey} gatewaySessionKey=${gatewaySessionKey} jobId=${input.jobId ?? "(none)"} agentId=${input.agentId ?? "(none)"} messageId=${input.messageId ?? "(none)"}`
86595
86386
  );
86596
86387
  try {
@@ -86599,7 +86390,7 @@ var GatewayOutboundBehavior = class {
86599
86390
  message: input.content,
86600
86391
  ...input.messageId ? { idempotencyKey: input.messageId } : {}
86601
86392
  });
86602
- console.error(
86393
+ errorWithTimestamp(
86603
86394
  `${GATEWAY_OUTBOUND_LOG_PREFIX} dispatchSessionMessage ok sessionKey=${input.sessionKey} gatewaySessionKey=${gatewaySessionKey} messageId=${input.messageId ?? "(none)"}`
86604
86395
  );
86605
86396
  logger.info(LogEvent.SESSION_DISPATCHED, gatewayOutboundExtra("sessions.send", {
@@ -86628,7 +86419,7 @@ var GatewayOutboundBehavior = class {
86628
86419
  jobId: input.jobId ?? null,
86629
86420
  messageId: input.messageId ?? null
86630
86421
  });
86631
- console.error(
86422
+ errorWithTimestamp(
86632
86423
  `${GATEWAY_OUTBOUND_LOG_PREFIX} dispatchSessionMessage buffered sessionKey=${input.sessionKey} gatewaySessionKey=${gatewaySessionKey} messageId=${input.messageId ?? "(none)"}: ${err2 instanceof Error ? err2.message : String(err2)}`
86633
86424
  );
86634
86425
  logger.error(LogEvent.GATEWAY_REQUEST_FAILED, err2 instanceof Error ? err2 : new Error(String(err2)), gatewayOutboundExtra("sessions.send", {
@@ -86658,22 +86449,13 @@ var GatewayOutboundBehavior = class {
86658
86449
  });
86659
86450
  }
86660
86451
  async dispatchUser(input) {
86661
- const routed = this.resolveUserGatewaySessionKey(input);
86662
- if (routed) {
86663
- await this.dispatchUserToGatewaySession(input, routed);
86664
- return null;
86665
- }
86666
- console.error(
86452
+ errorWithTimestamp(
86667
86453
  `${GATEWAY_OUTBOUND_LOG_PREFIX} dispatchUser latestUserSessions jobId=${input.jobId ?? "(none)"} idempotencyKey=${input.idempotencyKey ?? "(none)"}`
86668
86454
  );
86669
86455
  try {
86670
- const result = await this.gateway.callDispatchUserToLatestSessions({
86671
- content: input.userContent,
86672
- ...input.jobId ? { jobId: input.jobId } : {},
86673
- ...input.sessionKey ? { currentSessionKey: input.sessionKey } : {}
86674
- });
86456
+ const result = await this.gateway.callDispatchUserToLatestSessions({ content: input.userContent });
86675
86457
  assertLatestUserFanoutDelivered("okx-a2a.dispatch_user", result);
86676
- console.error(`${GATEWAY_OUTBOUND_LOG_PREFIX} dispatchUser latestUserSessions ok`);
86458
+ errorWithTimestamp(`${GATEWAY_OUTBOUND_LOG_PREFIX} dispatchUser latestUserSessions ok`);
86677
86459
  logger.info(LogEvent.USER_DISPATCHED, gatewayOutboundExtra("okx-a2a.dispatch_user", {
86678
86460
  jobId: input.jobId ?? "",
86679
86461
  status: "delivered"
@@ -86694,7 +86476,7 @@ var GatewayOutboundBehavior = class {
86694
86476
  jobId: input.jobId ?? null,
86695
86477
  messageId: input.idempotencyKey ?? null
86696
86478
  });
86697
- console.error(
86479
+ errorWithTimestamp(
86698
86480
  `${GATEWAY_OUTBOUND_LOG_PREFIX} dispatchUser latestUserSessions buffered idempotencyKey=${input.idempotencyKey ?? "(none)"}: ${err2 instanceof Error ? err2.message : String(err2)}`
86699
86481
  );
86700
86482
  logger.error(LogEvent.USER_DISPATCH_FAILED, err2 instanceof Error ? err2 : new Error(String(err2)), gatewayOutboundExtra("okx-a2a.dispatch_user", {
@@ -86709,93 +86491,17 @@ var GatewayOutboundBehavior = class {
86709
86491
  }
86710
86492
  return null;
86711
86493
  }
86712
- resolveUserGatewaySessionKey(input) {
86713
- const routes = resolveOpenClawGatewayRoutes(this.sessionMetaStore, input);
86714
- if (routes.length > 0) {
86715
- return { sessionKeys: routes.map((route) => route.sessionKey), source: "stored_openclaw_routes" };
86716
- }
86717
- if (input.sessionKey?.startsWith("agent:")) {
86718
- return isValidOpenClawGatewaySessionKey(input.sessionKey) ? { sessionKeys: [input.sessionKey], source: "explicit_gateway_session" } : null;
86719
- }
86720
- return null;
86721
- }
86722
- async dispatchUserToGatewaySession(input, routed) {
86723
- const gatewaySessionKey = routed.sessionKeys.join(",");
86724
- console.error(
86725
- `${GATEWAY_OUTBOUND_LOG_PREFIX} dispatchUser routed sessionKey=${input.sessionKey ?? "(none)"} gatewaySessionKey=${gatewaySessionKey} source=${routed.source} jobId=${input.jobId ?? "(none)"} idempotencyKey=${input.idempotencyKey ?? "(none)"}`
86726
- );
86727
- try {
86728
- const result = await this.gateway.callDispatchUserToLatestSessions({
86729
- content: input.userContent,
86730
- label: "okx-a2a",
86731
- ...routed.source === "stored_openclaw_routes" ? { sessionKeys: routed.sessionKeys } : { sessionKey: routed.sessionKeys[0] }
86732
- });
86733
- assertLatestUserFanoutDelivered("okx-a2a.dispatch_user", result);
86734
- console.error(`${GATEWAY_OUTBOUND_LOG_PREFIX} dispatchUser routed ok gatewaySessionKey=${gatewaySessionKey} source=${routed.source}`);
86735
- logger.info(LogEvent.USER_DISPATCHED, gatewayOutboundExtra("okx-a2a.dispatch_user", {
86736
- sessionKey: input.sessionKey ?? "",
86737
- gatewaySessionKey,
86738
- jobId: input.jobId ?? "",
86739
- source: routed.source,
86740
- status: "delivered"
86741
- }));
86742
- } catch (err2) {
86743
- if (!this.store || !isRetryableOpenClawGatewayError(err2)) {
86744
- logger.error(LogEvent.USER_DISPATCH_FAILED, err2 instanceof Error ? err2 : new Error(String(err2)), gatewayOutboundExtra("okx-a2a.dispatch_user", {
86745
- sessionKey: input.sessionKey ?? "",
86746
- gatewaySessionKey,
86747
- jobId: input.jobId ?? "",
86748
- source: routed.source,
86749
- status: "failed"
86750
- }));
86751
- throw err2;
86752
- }
86753
- this.store.enqueuePendingGatewayDelivery({
86754
- kind: "chat_inject",
86755
- provider: this.provider,
86756
- sessionKey: routed.sessionKeys[0] ?? "openclaw:routed-user-sessions",
86757
- content: input.userContent,
86758
- jobId: input.jobId ?? null,
86759
- messageId: input.idempotencyKey ?? null
86760
- });
86761
- console.error(
86762
- `${GATEWAY_OUTBOUND_LOG_PREFIX} dispatchUser routed buffered gatewaySessionKey=${gatewaySessionKey} source=${routed.source} idempotencyKey=${input.idempotencyKey ?? "(none)"}: ${err2 instanceof Error ? err2.message : String(err2)}`
86763
- );
86764
- logger.error(LogEvent.USER_DISPATCH_FAILED, err2 instanceof Error ? err2 : new Error(String(err2)), gatewayOutboundExtra("okx-a2a.dispatch_user", {
86765
- sessionKey: input.sessionKey ?? "",
86766
- gatewaySessionKey,
86767
- jobId: input.jobId ?? "",
86768
- source: routed.source,
86769
- status: "buffered"
86770
- }));
86771
- logger.info(LogEvent.GATEWAY_DELIVERY_BUFFERED, gatewayOutboundExtra("okx-a2a.dispatch_user", {
86772
- sessionKey: input.sessionKey ?? "",
86773
- gatewaySessionKey,
86774
- jobId: input.jobId ?? "",
86775
- messageId: input.idempotencyKey ?? "",
86776
- source: routed.source,
86777
- status: "buffered"
86778
- }));
86779
- }
86780
- }
86781
86494
  async promptUser(input) {
86782
- const routed = this.resolveUserGatewaySessionKey(input);
86783
- if (routed) {
86784
- await this.promptUserToGatewaySession(input, routed);
86785
- return null;
86786
- }
86787
- console.error(
86495
+ errorWithTimestamp(
86788
86496
  `${GATEWAY_OUTBOUND_LOG_PREFIX} promptUser latestUserSessions jobId=${input.jobId ?? "(none)"} idempotencyKey=${input.idempotencyKey ?? "(none)"}`
86789
86497
  );
86790
86498
  try {
86791
86499
  const result = await this.gateway.callPromptUserToLatestSessions({
86792
86500
  userContent: input.userContent,
86793
- llmContent: input.llmContent,
86794
- ...input.jobId ? { jobId: input.jobId } : {},
86795
- ...input.sessionKey ? { currentSessionKey: input.sessionKey } : {}
86501
+ llmContent: input.llmContent
86796
86502
  });
86797
86503
  assertLatestUserFanoutDelivered("okx-a2a.prompt_user", result);
86798
- console.error(`${GATEWAY_OUTBOUND_LOG_PREFIX} promptUser latestUserSessions ok`);
86504
+ errorWithTimestamp(`${GATEWAY_OUTBOUND_LOG_PREFIX} promptUser latestUserSessions ok`);
86799
86505
  logger.info(LogEvent.PROMPT_USER_CHECKPOINT, gatewayOutboundExtra("okx-a2a.prompt_user", {
86800
86506
  jobId: input.jobId ?? "",
86801
86507
  status: "delivered"
@@ -86817,7 +86523,7 @@ var GatewayOutboundBehavior = class {
86817
86523
  jobId: input.jobId ?? null,
86818
86524
  messageId: input.idempotencyKey ?? null
86819
86525
  });
86820
- console.error(
86526
+ errorWithTimestamp(
86821
86527
  `${GATEWAY_OUTBOUND_LOG_PREFIX} promptUser latestUserSessions buffered idempotencyKey=${input.idempotencyKey ?? "(none)"}: ${err2 instanceof Error ? err2.message : String(err2)}`
86822
86528
  );
86823
86529
  logger.error(LogEvent.PROMPT_USER_FAILED, err2 instanceof Error ? err2 : new Error(String(err2)), gatewayOutboundExtra("okx-a2a.prompt_user", {
@@ -86832,66 +86538,6 @@ var GatewayOutboundBehavior = class {
86832
86538
  }
86833
86539
  return null;
86834
86540
  }
86835
- async promptUserToGatewaySession(input, routed) {
86836
- const gatewaySessionKey = routed.sessionKeys.join(",");
86837
- console.error(
86838
- `${GATEWAY_OUTBOUND_LOG_PREFIX} promptUser routed sessionKey=${input.sessionKey ?? "(none)"} gatewaySessionKey=${gatewaySessionKey} source=${routed.source} jobId=${input.jobId ?? "(none)"} idempotencyKey=${input.idempotencyKey ?? "(none)"}`
86839
- );
86840
- try {
86841
- const result = await this.gateway.callPromptUserToLatestSessions({
86842
- userContent: input.userContent,
86843
- llmContent: input.llmContent,
86844
- ...routed.source === "stored_openclaw_routes" ? { sessionKeys: routed.sessionKeys } : { sessionKey: routed.sessionKeys[0] }
86845
- });
86846
- assertLatestUserFanoutDelivered("okx-a2a.prompt_user", result);
86847
- console.error(`${GATEWAY_OUTBOUND_LOG_PREFIX} promptUser routed ok gatewaySessionKey=${gatewaySessionKey} source=${routed.source}`);
86848
- logger.info(LogEvent.PROMPT_USER_CHECKPOINT, gatewayOutboundExtra("routed_prompt_user", {
86849
- sessionKey: input.sessionKey ?? "",
86850
- gatewaySessionKey,
86851
- jobId: input.jobId ?? "",
86852
- source: routed.source,
86853
- status: "delivered"
86854
- }));
86855
- } catch (err2) {
86856
- if (!this.store || !isRetryableOpenClawGatewayError(err2)) {
86857
- logger.error(LogEvent.PROMPT_USER_FAILED, err2 instanceof Error ? err2 : new Error(String(err2)), gatewayOutboundExtra("routed_prompt_user", {
86858
- sessionKey: input.sessionKey ?? "",
86859
- gatewaySessionKey,
86860
- jobId: input.jobId ?? "",
86861
- source: routed.source,
86862
- status: "failed"
86863
- }));
86864
- throw err2;
86865
- }
86866
- this.store.enqueuePendingGatewayDelivery({
86867
- kind: "chat_inject",
86868
- provider: this.provider,
86869
- sessionKey: routed.sessionKeys[0] ?? "openclaw:routed-user-sessions",
86870
- content: input.userContent,
86871
- llmContent: input.llmContent,
86872
- jobId: input.jobId ?? null,
86873
- messageId: input.idempotencyKey ?? null
86874
- });
86875
- console.error(
86876
- `${GATEWAY_OUTBOUND_LOG_PREFIX} promptUser routed buffered gatewaySessionKey=${gatewaySessionKey} source=${routed.source} idempotencyKey=${input.idempotencyKey ?? "(none)"}: ${err2 instanceof Error ? err2.message : String(err2)}`
86877
- );
86878
- logger.error(LogEvent.PROMPT_USER_FAILED, err2 instanceof Error ? err2 : new Error(String(err2)), gatewayOutboundExtra("routed_prompt_user", {
86879
- sessionKey: input.sessionKey ?? "",
86880
- gatewaySessionKey,
86881
- jobId: input.jobId ?? "",
86882
- source: routed.source,
86883
- status: "buffered"
86884
- }));
86885
- logger.info(LogEvent.GATEWAY_DELIVERY_BUFFERED, gatewayOutboundExtra("routed_prompt_user", {
86886
- sessionKey: input.sessionKey ?? "",
86887
- gatewaySessionKey,
86888
- jobId: input.jobId ?? "",
86889
- messageId: input.idempotencyKey ?? "",
86890
- source: routed.source,
86891
- status: "buffered"
86892
- }));
86893
- }
86894
- }
86895
86541
  };
86896
86542
  function createOutboundBehavior(provider, deps) {
86897
86543
  if (provider === "openclaw") {
@@ -86980,27 +86626,15 @@ function resolveOutboundProvider(store, input) {
86980
86626
  if (input.override) {
86981
86627
  return input.override;
86982
86628
  }
86983
- if (input.jobId && resolveOpenClawGatewayRoute(store, { jobId: input.jobId })) {
86984
- return "openclaw";
86985
- }
86986
86629
  try {
86987
- const configured = resolveConfiguredAiProviderForJob({
86630
+ return resolveConfiguredAiProviderForJob({
86988
86631
  store,
86989
86632
  jobId: input.jobId,
86990
86633
  env: process.env
86991
- });
86992
- if (configured) {
86993
- return configured;
86994
- }
86634
+ }) ?? "codex";
86995
86635
  } catch {
86636
+ return "codex";
86996
86637
  }
86997
- if (readSyncedOpenClawGatewayConfig(store.homeDir)) {
86998
- if (input.jobId?.trim()) {
86999
- return store.bindJobProviderIfMissing({ jobId: input.jobId.trim(), provider: "openclaw" }).binding.provider;
87000
- }
87001
- return "openclaw";
87002
- }
87003
- return "codex";
87004
86638
  }
87005
86639
  async function notifyAgentMessageToUserAttention(input) {
87006
86640
  const ownedStore = input.store ? null : new SessionStore();
@@ -87019,12 +86653,12 @@ async function notifyAgentMessageToUserAttention(input) {
87019
86653
  sessionKey: input.sessionKey ?? null,
87020
86654
  idempotencyKey
87021
86655
  });
87022
- console.log(
86656
+ logWithTimestamp(
87023
86657
  `[notifyAgentMessageToUserAttention] provider=${provider} direction=${input.direction} job=${input.jobId} item=${item?.id ?? "(gateway)"}`
87024
86658
  );
87025
86659
  return item;
87026
86660
  } catch (err2) {
87027
- console.log(
86661
+ logWithTimestamp(
87028
86662
  `[notifyAgentMessageToUserAttention] failed direction=${input.direction} job=${input.jobId}:`,
87029
86663
  err2
87030
86664
  );
@@ -87050,12 +86684,12 @@ async function notifySystemMessageToUser(input) {
87050
86684
  sessionKey: input.sessionKey ?? null,
87051
86685
  idempotencyKey
87052
86686
  });
87053
- console.log(
86687
+ logWithTimestamp(
87054
86688
  `[notifySystemMessageToUser] provider=${provider} title=${input.title} item=${item?.id ?? "(gateway)"}`
87055
86689
  );
87056
86690
  return item;
87057
86691
  } catch (err2) {
87058
- console.log(
86692
+ logWithTimestamp(
87059
86693
  `[notifySystemMessageToUser] failed title=${input.title}:`,
87060
86694
  err2
87061
86695
  );
@@ -87114,7 +86748,7 @@ function assertRecipientAvailable(agent) {
87114
86748
  }
87115
86749
  }
87116
86750
  function logRecipientStatusLookupFailed(context, err2) {
87117
- console.log(`[okx-agent-task] recipient status lookup failed, continuing (${context}):`, err2);
86751
+ logWithTimestamp(`[okx-agent-task] recipient status lookup failed, continuing (${context}):`, err2);
87118
86752
  }
87119
86753
  function bindOutboundJobProviderToCurrentDefault(sessionStore, jobId) {
87120
86754
  if (!jobId || jobId === BACKUP_JOB_ID) {
@@ -87126,15 +86760,12 @@ function bindOutboundJobProviderToCurrentDefault(sessionStore, jobId) {
87126
86760
  jobId
87127
86761
  });
87128
86762
  if (result?.created) {
87129
- console.log(`[okx-agent-task] job provider bound from outbound-xmtp: job=${jobId} provider=${result.provider}`);
86763
+ logWithTimestamp(`[okx-agent-task] job provider bound from outbound-xmtp: job=${jobId} provider=${result.provider}`);
87130
86764
  }
87131
86765
  } catch (err2) {
87132
- console.log(`[okx-agent-task] job provider bind failed from outbound-xmtp: job=${jobId}`, err2);
86766
+ logWithTimestamp(`[okx-agent-task] job provider bind failed from outbound-xmtp: job=${jobId}`, err2);
87133
86767
  }
87134
86768
  }
87135
- function bindOutboundOpenClawRouteIfCurrent(sessionStore, jobId, gatewaySessionKeys) {
87136
- bindOpenClawGatewayRouteFromEnv(sessionStore, { jobId, gatewaySessionKeys });
87137
- }
87138
86769
  function buildTaskPayload(replyToMessageId) {
87139
86770
  return {
87140
86771
  taskMinVersion: TASK_MIN_VERSION,
@@ -87280,13 +86911,13 @@ async function assertOutboundEligible(params) {
87280
86911
  providerSecurityRate
87281
86912
  });
87282
86913
  } catch (err2) {
87283
- console.log(
86914
+ logWithTimestamp(
87284
86915
  `[okx-agent-task] outbound message-eligible call failed, letting send continue: senderAgentId=${senderAgent.agentId} receiverAgentId=${receiverAgent.agentId} job=${jobId} group=${groupId}`,
87285
86916
  err2
87286
86917
  );
87287
86918
  return;
87288
86919
  }
87289
- console.log(
86920
+ logWithTimestamp(
87290
86921
  `[okx-agent-task] outbound message-eligible: senderAgentId=${senderAgent.agentId} receiverAgentId=${receiverAgent.agentId} job=${jobId} group=${groupId} result=${JSON.stringify(result)}`
87291
86922
  );
87292
86923
  if (!result.eligible) {
@@ -87362,7 +86993,7 @@ async function refreshCachedBlockedAgentById(agentId, cached) {
87362
86993
  const [remote] = await fetchAgentsByIds([agentId]);
87363
86994
  if (remote?.agentId) {
87364
86995
  cacheResolvedAgent(remote);
87365
- console.log(
86996
+ logWithTimestamp(
87366
86997
  `[okx-agent-task] refreshed blocked recipient cache by agentId=${agentId}: oldStatus=${cached.status} newStatus=${remote.status}`
87367
86998
  );
87368
86999
  return remote;
@@ -87380,7 +87011,7 @@ async function refreshCachedBlockedAgentByAddress(communicationAddress, cached)
87380
87011
  const remote = await fetchAgentByAddress(communicationAddress);
87381
87012
  if (remote?.agentId) {
87382
87013
  cacheResolvedAgent(remote);
87383
- console.log(
87014
+ logWithTimestamp(
87384
87015
  `[okx-agent-task] refreshed blocked recipient cache by address=${communicationAddress}: oldStatus=${cached.status} newStatus=${remote.status}`
87385
87016
  );
87386
87017
  return remote;
@@ -87434,7 +87065,7 @@ async function resolveRemoteByAgentId(params) {
87434
87065
  const fallbackAgent = await resolveAgentByAddressFromCacheOrNetwork(service, fallbackAddress);
87435
87066
  remoteAgent = fallbackAgent ?? remoteAgent;
87436
87067
  } catch (err2) {
87437
- console.log(
87068
+ logWithTimestamp(
87438
87069
  `[okx-agent-task] remote agent lookup failed for ${fallbackAddress}, continuing without receiverAgentId:`,
87439
87070
  err2
87440
87071
  );
@@ -87466,7 +87097,7 @@ async function resolveRemote(params) {
87466
87097
  try {
87467
87098
  remoteAgent = await resolveAgentByAddressFromCacheOrNetwork(service, toXmtpAddress);
87468
87099
  } catch (err2) {
87469
- console.log(
87100
+ logWithTimestamp(
87470
87101
  `[okx-agent-task] remote agent lookup failed for ${toXmtpAddress}, continuing without receiverAgentId:`,
87471
87102
  err2
87472
87103
  );
@@ -87497,7 +87128,7 @@ async function resolveRemoteWithoutFile(params) {
87497
87128
  try {
87498
87129
  remoteAgent = await resolveAgentByAddressFromCacheOrNetwork(service, command.toXmtpAddress);
87499
87130
  } catch (err2) {
87500
- console.log(
87131
+ logWithTimestamp(
87501
87132
  `[okx-agent-task] remote agent lookup failed for ${command.toXmtpAddress}, continuing without receiverAgentId:`,
87502
87133
  err2
87503
87134
  );
@@ -87571,7 +87202,6 @@ async function handleSqliteGroupSendCommand(params) {
87571
87202
  myAgentXmtpAddress: myXmtpAddress,
87572
87203
  toAgentXmtpAddress: remote.toXmtpAddress
87573
87204
  });
87574
- bindOutboundOpenClawRouteIfCurrent(sessionStore, command.jobId, command.gatewaySessionKeys);
87575
87205
  return { conversation: conversation2, created: created2 };
87576
87206
  }
87577
87207
  );
@@ -87594,7 +87224,7 @@ async function handleSqliteGroupSendCommand(params) {
87594
87224
  receiverAgentId: remote.remoteAgent?.agentId ?? remote.toAgentId ?? null,
87595
87225
  payload: buildTaskPayload(command.replyToMessageId)
87596
87226
  });
87597
- console.log(`[okx-agent-task] xmtp envelope ${rawText}`);
87227
+ logWithTimestamp(`[okx-agent-task] xmtp envelope ${rawText}`);
87598
87228
  await conversation.send(rawText);
87599
87229
  const messageId = `outbound-${(0, import_node_crypto8.randomUUID)()}`;
87600
87230
  await notifyAgentMessageToUserAttention({
@@ -87615,7 +87245,7 @@ async function handleSqliteGroupSendCommand(params) {
87615
87245
  content: command.message,
87616
87246
  store: sessionStore
87617
87247
  });
87618
- console.log(
87248
+ logWithTimestamp(
87619
87249
  `[okx-agent-task] sent xmtp message via sqlite session=${sessionKey} group=${conversation.id} created=${created}`
87620
87250
  );
87621
87251
  return { messageId };
@@ -87731,7 +87361,7 @@ async function handleGroupSendCommand(params) {
87731
87361
  receiverAgentId: remoteAgent?.agentId ?? session.toAgentId ?? null,
87732
87362
  payload: buildTaskPayload(command.replyToMessageId)
87733
87363
  });
87734
- console.log(`[okx-agent-task] xmtp envelope ${rawText}`);
87364
+ logWithTimestamp(`[okx-agent-task] xmtp envelope ${rawText}`);
87735
87365
  await conversation.send(rawText);
87736
87366
  const now = Date.now();
87737
87367
  const messageId = `outbound-${(0, import_node_crypto8.randomUUID)()}`;
@@ -87898,7 +87528,7 @@ async function handleXmtpSendCommand(params) {
87898
87528
  const sessionStore2 = params.sessionStore ?? ownedStore2;
87899
87529
  try {
87900
87530
  bindOutboundJobProviderToCurrentDefault(sessionStore2, command.jobId);
87901
- bindOutboundOpenClawRouteIfCurrent(sessionStore2, command.jobId, command.gatewaySessionKeys);
87531
+ resolveConfiguredAiProviderForJob({ store: sessionStore2, jobId: command.jobId });
87902
87532
  return await handleSqliteGroupSendCommand({
87903
87533
  command,
87904
87534
  service,
@@ -87912,7 +87542,7 @@ async function handleXmtpSendCommand(params) {
87912
87542
  const sessionStore = params.sessionStore ?? ownedStore;
87913
87543
  try {
87914
87544
  bindOutboundJobProviderToCurrentDefault(sessionStore, command.jobId);
87915
- bindOutboundOpenClawRouteIfCurrent(sessionStore, command.jobId, command.gatewaySessionKeys);
87545
+ resolveConfiguredAiProviderForJob({ store: sessionStore, jobId: command.jobId });
87916
87546
  const { file, sessionAgentId } = await readFileForSend({
87917
87547
  command,
87918
87548
  store,
@@ -88069,7 +87699,7 @@ function startCommandProcessor(params) {
88069
87699
  timeoutMs: staleTimeoutMs,
88070
87700
  reason: "pending_expired"
88071
87701
  }));
88072
- console.log(
87702
+ logWithTimestamp(
88073
87703
  `[okx-agent-task] ${command.type} command expired id=${command.id}: ${message}`
88074
87704
  );
88075
87705
  continue;
@@ -88085,7 +87715,7 @@ function startCommandProcessor(params) {
88085
87715
  `${command.type} command timed out after ${formatDuration2(executionTimeoutMs)}`
88086
87716
  );
88087
87717
  await commands.complete(command, result);
88088
- console.log(formatCommandCompleted(command, result));
87718
+ logWithTimestamp(formatCommandCompleted(command, result));
88089
87719
  } catch (err2) {
88090
87720
  const message = err2 instanceof Error ? err2.message : String(err2);
88091
87721
  await commands.complete(command, {
@@ -88105,7 +87735,7 @@ function startCommandProcessor(params) {
88105
87735
  if (command.type === "xmtp-send") {
88106
87736
  await notifyCommandFailure(params, command, message);
88107
87737
  }
88108
- console.log(
87738
+ logWithTimestamp(
88109
87739
  `[okx-agent-task] ${command.type} command failed id=${command.id}: ${message}`
88110
87740
  );
88111
87741
  }
@@ -88120,7 +87750,7 @@ function startCommandProcessor(params) {
88120
87750
  reason: "tick_exception"
88121
87751
  }
88122
87752
  );
88123
- console.log("[okx-agent-task] command processor tick failed:", err2);
87753
+ logWithTimestamp("[okx-agent-task] command processor tick failed:", err2);
88124
87754
  } finally {
88125
87755
  inFlight = false;
88126
87756
  }
@@ -88158,7 +87788,7 @@ function startCommandProcessor(params) {
88158
87788
  timeoutMs: aiStaleTimeoutMs,
88159
87789
  reason: "pending_expired"
88160
87790
  }));
88161
- console.log(
87791
+ logWithTimestamp(
88162
87792
  `[okx-agent-task] ${command.type}/${command.kind} command expired id=${command.id}: ${message}`
88163
87793
  );
88164
87794
  continue;
@@ -88182,7 +87812,7 @@ function startCommandProcessor(params) {
88182
87812
  reason: "tick_exception"
88183
87813
  }
88184
87814
  );
88185
- console.log("[okx-agent-task] AI command processor tick failed:", err2);
87815
+ logWithTimestamp("[okx-agent-task] AI command processor tick failed:", err2);
88186
87816
  } finally {
88187
87817
  aiScanInFlight = false;
88188
87818
  }
@@ -88191,7 +87821,7 @@ function startCommandProcessor(params) {
88191
87821
  try {
88192
87822
  const result = await handleDaemonCommand(command, { ...params, aiRunner, commandPendingMs });
88193
87823
  await commands.complete(command, result);
88194
- console.log(formatCommandCompleted(command, result));
87824
+ logWithTimestamp(formatCommandCompleted(command, result));
88195
87825
  } catch (err2) {
88196
87826
  const message = err2 instanceof Error ? err2.message : String(err2);
88197
87827
  await commands.complete(command, {
@@ -88207,7 +87837,7 @@ function startCommandProcessor(params) {
88207
87837
  reason: isTimeout ? "ai_timeout" : "ai_error"
88208
87838
  })
88209
87839
  );
88210
- console.log(
87840
+ logWithTimestamp(
88211
87841
  `[okx-agent-task] ${command.type}/${command.kind} command failed id=${command.id}: ${message}`
88212
87842
  );
88213
87843
  } finally {
@@ -88488,7 +88118,7 @@ async function failStaleProcessing(commands, params, staleTimeoutMs, aiStaleTime
88488
88118
  if (entry.command.type === "xmtp-send") {
88489
88119
  await notifyCommandFailure(params, entry.command, message);
88490
88120
  }
88491
- console.log(
88121
+ logWithTimestamp(
88492
88122
  `[okx-agent-task] recovered stale ${entry.command.type} command id=${entry.command.id}: ${message}`
88493
88123
  );
88494
88124
  }
@@ -88552,9 +88182,9 @@ async function notifyCommandFailure(params, command, message) {
88552
88182
  ].join("\n")
88553
88183
  });
88554
88184
  await notifyUserAttentionChanged(params.homeDir ?? params.sessionStore.homeDir);
88555
- console.log(`[okx-agent-task] queued xmtp-send failure notification todo=${item.id} command=${command.id}`);
88185
+ logWithTimestamp(`[okx-agent-task] queued xmtp-send failure notification todo=${item.id} command=${command.id}`);
88556
88186
  } catch (err2) {
88557
- console.log(`[okx-agent-task] failed to notify xmtp-send failure command=${command.id}:`, err2);
88187
+ logWithTimestamp(`[okx-agent-task] failed to notify xmtp-send failure command=${command.id}:`, err2);
88558
88188
  }
88559
88189
  }
88560
88190
  function readPositiveEnv(name2, fallback) {
@@ -88635,7 +88265,7 @@ function extractRawText(content3) {
88635
88265
  }
88636
88266
  return safeStringify(content3);
88637
88267
  }
88638
- function extractXmtpSentAtMs(msg) {
88268
+ function extractXmtpSentAtMs2(msg) {
88639
88269
  if (typeof msg.sentAtNs === "bigint") {
88640
88270
  return Number(msg.sentAtNs / 1000000n);
88641
88271
  }
@@ -88773,12 +88403,12 @@ function bindMessageJobProviderToCurrentDefault(deps, jobId, stage = "inbound-xm
88773
88403
  return { allowed: true, created: false, provider: null, currentProvider };
88774
88404
  }
88775
88405
  if (result?.created) {
88776
- console.log(
88406
+ logWithTimestamp(
88777
88407
  `[okx-agent-task:${deps.myXmtpAddress}] job provider bound from ${stage}: job=${shortenLogValue(jobId)} provider=${result.provider}`
88778
88408
  );
88779
88409
  }
88780
88410
  if (currentProvider && result.provider !== currentProvider) {
88781
- console.log(
88411
+ logWithTimestamp(
88782
88412
  `[okx-agent-task:${deps.myXmtpAddress}] job provider owner differs from default at ${stage}: job=${shortenLogValue(jobId)} owner=${result.provider} default=${currentProvider}; dispatch will use owner binding`
88783
88413
  );
88784
88414
  }
@@ -88789,7 +88419,7 @@ function bindMessageJobProviderToCurrentDefault(deps, jobId, stage = "inbound-xm
88789
88419
  currentProvider
88790
88420
  };
88791
88421
  } catch (err2) {
88792
- console.log(
88422
+ logWithTimestamp(
88793
88423
  `[okx-agent-task:${deps.myXmtpAddress}] job provider bind failed from ${stage}: job=${shortenLogValue(jobId)}`,
88794
88424
  err2
88795
88425
  );
@@ -88863,7 +88493,7 @@ async function maybeAllowProviderGroup(deps, chatType, conversationId) {
88863
88493
  try {
88864
88494
  await deps.allowGroup(deps.myXmtpAddress, conversationId);
88865
88495
  } catch (err2) {
88866
- console.log(
88496
+ logWithTimestamp(
88867
88497
  `[okx-agent-task:${deps.myXmtpAddress}] allowGroup failed for ${conversationId}:`,
88868
88498
  err2
88869
88499
  );
@@ -88887,7 +88517,7 @@ function notifyPendingConversationToBackup(params) {
88887
88517
  messageId: params.messageId
88888
88518
  });
88889
88519
  void Promise.resolve(params.deps.onSessionMessage?.(event)).catch((err2) => {
88890
- console.log(`[okx-agent-task:${params.deps.myXmtpAddress}] pending conversation backup dispatch failed:`, err2);
88520
+ logWithTimestamp(`[okx-agent-task:${params.deps.myXmtpAddress}] pending conversation backup dispatch failed:`, err2);
88891
88521
  });
88892
88522
  }
88893
88523
  function maybeNotifyInboundAgentMessage(params) {
@@ -88903,7 +88533,7 @@ function maybeNotifyInboundAgentMessage(params) {
88903
88533
  messageId: params.messageId,
88904
88534
  store: params.deps.sessionStore
88905
88535
  }).catch((err2) => {
88906
- console.log(`[okx-agent-task:${params.deps.myXmtpAddress}] system user notification failed:`, err2);
88536
+ logWithTimestamp(`[okx-agent-task:${params.deps.myXmtpAddress}] system user notification failed:`, err2);
88907
88537
  });
88908
88538
  return;
88909
88539
  }
@@ -88932,7 +88562,7 @@ function maybeNotifyInboundAgentMessage(params) {
88932
88562
  content: content3,
88933
88563
  store: params.deps.sessionStore
88934
88564
  }).catch((err2) => {
88935
- console.log(`[okx-agent-task:${params.deps.myXmtpAddress}] inbound user notification failed:`, err2);
88565
+ logWithTimestamp(`[okx-agent-task:${params.deps.myXmtpAddress}] inbound user notification failed:`, err2);
88936
88566
  });
88937
88567
  }
88938
88568
  function stringifySystemPayload(payload) {
@@ -89007,7 +88637,7 @@ async function isTrustedDmSender(params) {
89007
88637
  }
89008
88638
  if (!matches(trustedInboxIds)) {
89009
88639
  logger.info(LogEvent.INBOUND_DROP_DM_NON_SYSTEM, { ...dmExtras(), reason: "sender_not_in_system_whitelist" });
89010
- console.log(
88640
+ logWithTimestamp(
89011
88641
  `[okx-agent-task:${myXmtpAddress}] DM sender not in system whitelist, dropping: senderInboxId=${senderInboxId || "(empty)"}`
89012
88642
  );
89013
88643
  return false;
@@ -89040,7 +88670,7 @@ async function claimedAddressMatchesSender(params) {
89040
88670
  });
89041
88671
  return !!claimedInboxId && !!senderInboxId && claimedInboxId.toLowerCase() === senderInboxId.toLowerCase();
89042
88672
  } catch (err2) {
89043
- console.log(
88673
+ logWithTimestamp(
89044
88674
  `[okx-agent-task:${myXmtpAddress}] getInboxIdByIdentifier failed, blocking address check:`,
89045
88675
  err2
89046
88676
  );
@@ -89073,7 +88703,7 @@ function recordInvalidXmtpMessageBestEffort(input) {
89073
88703
  store.close();
89074
88704
  }
89075
88705
  } catch (err2) {
89076
- console.log(`${input.logTag} failed to record invalid xmtp message ${input.messageId}:`, err2);
88706
+ logWithTimestamp(`${input.logTag} failed to record invalid xmtp message ${input.messageId}:`, err2);
89077
88707
  }
89078
88708
  }
89079
88709
  async function verifyInboundA2AGroupMessage(params) {
@@ -89086,13 +88716,14 @@ async function verifyInboundA2AGroupMessage(params) {
89086
88716
  groupId,
89087
88717
  messageId,
89088
88718
  consentState,
89089
- trustedSystemSender = false
88719
+ trustedSystemSender = false,
88720
+ timing
89090
88721
  } = params;
89091
88722
  if (!isA2AEnvelope(payload)) {
89092
88723
  return true;
89093
88724
  }
89094
88725
  if (trustedSystemSender) {
89095
- console.log(
88726
+ logWithTimestamp(
89096
88727
  `[okx-agent-task:${myXmtpAddress}] trusted system/security group sender, skipping inbound policy checks: sender=${senderAddress} job=${jobId} group=${groupId}`
89097
88728
  );
89098
88729
  return true;
@@ -89100,14 +88731,20 @@ async function verifyInboundA2AGroupMessage(params) {
89100
88731
  const service = XmtpService.getInstance();
89101
88732
  const myAgent = service.getAgentByAddress(myXmtpAddress);
89102
88733
  const claimedAddress = readString3(payload.fromXmtpAddress);
89103
- if (claimedAddress && !await claimedAddressMatchesSender({
89104
- myXmtpAddress,
89105
- claimedAddress,
89106
- senderAddress,
89107
- senderInboxId,
89108
- messageId,
89109
- conversationId: groupId
89110
- })) {
88734
+ let claimedAddressMatches = true;
88735
+ if (claimedAddress) {
88736
+ const addressCheckStartedAt = Date.now();
88737
+ claimedAddressMatches = await claimedAddressMatchesSender({
88738
+ myXmtpAddress,
88739
+ claimedAddress,
88740
+ senderAddress,
88741
+ senderInboxId,
88742
+ messageId,
88743
+ conversationId: groupId
88744
+ });
88745
+ timing?.mark("addressCheck", addressCheckStartedAt);
88746
+ }
88747
+ if (claimedAddress && !claimedAddressMatches) {
89111
88748
  const shouldAutoDeny = consentState === import_node_bindings2.ConsentState.Unknown && (myAgent?.role === 1 /* CLIENT */ || myAgent?.role == null);
89112
88749
  let autoDenyAttempted = false;
89113
88750
  let autoDenySucceeded = false;
@@ -89115,7 +88752,9 @@ async function verifyInboundA2AGroupMessage(params) {
89115
88752
  if (shouldAutoDeny) {
89116
88753
  autoDenyAttempted = true;
89117
88754
  try {
88755
+ const denyStartedAt = Date.now();
89118
88756
  autoDenySucceeded = await service.denyGroup(myXmtpAddress, groupId);
88757
+ timing?.mark("autoDeny", denyStartedAt);
89119
88758
  } catch (err2) {
89120
88759
  autoDenyError = err2 instanceof Error ? err2.message : String(err2);
89121
88760
  logger.error(LogEvent.GROUP_CONSENT_UPDATE_FAILED, err2 instanceof Error ? err2 : new Error(String(err2)), {
@@ -89131,7 +88770,7 @@ async function verifyInboundA2AGroupMessage(params) {
89131
88770
  });
89132
88771
  }
89133
88772
  }
89134
- console.log(
88773
+ logWithTimestamp(
89135
88774
  `[okx-agent-task:${myXmtpAddress}] address spoofing detected, dropping: claimed=${claimedAddress} actual=${senderAddress} autoDeny=${autoDenyAttempted ? String(autoDenySucceeded) : "skipped"}`
89136
88775
  );
89137
88776
  recordInvalidXmtpMessageBestEffort({
@@ -89159,7 +88798,8 @@ async function verifyInboundA2AGroupMessage(params) {
89159
88798
  action: autoDenyAttempted ? "auto-deny" : "drop",
89160
88799
  autoDenyAttempted: String(autoDenyAttempted),
89161
88800
  autoDenySucceeded: String(autoDenySucceeded),
89162
- autoDenyError
88801
+ autoDenyError,
88802
+ ...timing?.extras()
89163
88803
  });
89164
88804
  return false;
89165
88805
  }
@@ -89170,6 +88810,7 @@ async function verifyInboundA2AGroupMessage(params) {
89170
88810
  const isSenderClient = senderRole === 1 /* CLIENT */;
89171
88811
  const providerSecurityRate = (isSenderClient ? myAgent.securityRate : XmtpService.getInstance().getAgentStatusByAgentId(senderAgentId)?.securityRate) ?? 0;
89172
88812
  try {
88813
+ const eligibilityStartedAt = Date.now();
89173
88814
  const result = await checkMessageEligible({
89174
88815
  agentId: myAgent.agentId,
89175
88816
  clientAgentId: isSenderClient ? senderAgentId : myAgent.agentId,
@@ -89181,11 +88822,12 @@ async function verifyInboundA2AGroupMessage(params) {
89181
88822
  direction: isSenderClient ? "client_to_provider" : "provider_to_client",
89182
88823
  providerSecurityRate
89183
88824
  });
89184
- console.log(
88825
+ timing?.mark("eligibilityCheck", eligibilityStartedAt);
88826
+ logWithTimestamp(
89185
88827
  `[okx-agent-task:${myXmtpAddress}] inbound message-eligible: senderAgentId=${senderAgentId} job=${jobId} group=${groupId} result=${JSON.stringify(result)}`
89186
88828
  );
89187
88829
  if (!result.eligible) {
89188
- console.log(
88830
+ logWithTimestamp(
89189
88831
  `[okx-agent-task:${myXmtpAddress}] message-eligible check failed, dropping: sender=${senderAddress} job=${jobId} reason=${result.reason ?? ""}`
89190
88832
  );
89191
88833
  logger.info(LogEvent.INBOUND_BLOCKED_INELIGIBLE, {
@@ -89199,7 +88841,8 @@ async function verifyInboundA2AGroupMessage(params) {
89199
88841
  direction: isSenderClient ? "client_to_provider" : "provider_to_client",
89200
88842
  providerSecurityRate: String(providerSecurityRate),
89201
88843
  stage: "inbound/eligibility_check",
89202
- reason: result.reason ?? ""
88844
+ reason: result.reason ?? "",
88845
+ ...timing?.extras()
89203
88846
  });
89204
88847
  recordInvalidXmtpMessageBestEffort({
89205
88848
  messageId,
@@ -89216,7 +88859,7 @@ async function verifyInboundA2AGroupMessage(params) {
89216
88859
  return false;
89217
88860
  }
89218
88861
  } catch (err2) {
89219
- console.log(
88862
+ logWithTimestamp(
89220
88863
  `[okx-agent-task:${myXmtpAddress}] message-eligible call failed, letting message through:`,
89221
88864
  err2
89222
88865
  );
@@ -89231,7 +88874,8 @@ async function verifyInboundA2AGroupMessage(params) {
89231
88874
  direction: isSenderClient ? "client_to_provider" : "provider_to_client",
89232
88875
  providerSecurityRate: String(providerSecurityRate),
89233
88876
  stage: "inbound/eligibility_check",
89234
- reason: "exception"
88877
+ reason: "exception",
88878
+ ...timing?.extras()
89235
88879
  });
89236
88880
  }
89237
88881
  }
@@ -89240,11 +88884,13 @@ async function verifyInboundA2AGroupMessage(params) {
89240
88884
  return true;
89241
88885
  }
89242
88886
  try {
88887
+ const sensitiveStartedAt = Date.now();
89243
88888
  const hitWord = await service.checkSensitiveWord(content3);
88889
+ timing?.mark("sensitiveCheck", sensitiveStartedAt);
89244
88890
  if (!hitWord) {
89245
88891
  return true;
89246
88892
  }
89247
- console.log(
88893
+ logWithTimestamp(
89248
88894
  `[okx-agent-task:${myXmtpAddress}] sensitive word matched, dropping: job=${jobId} group=${groupId}`
89249
88895
  );
89250
88896
  logger.info(LogEvent.INBOUND_BLOCKED_SENSITIVE, {
@@ -89257,7 +88903,8 @@ async function verifyInboundA2AGroupMessage(params) {
89257
88903
  messageId,
89258
88904
  stage: "inbound/sensitive_check",
89259
88905
  reason: "sensitive_word",
89260
- hitWord
88906
+ hitWord,
88907
+ ...timing?.extras()
89261
88908
  });
89262
88909
  recordInvalidXmtpMessageBestEffort({
89263
88910
  messageId,
@@ -89273,7 +88920,7 @@ async function verifyInboundA2AGroupMessage(params) {
89273
88920
  });
89274
88921
  return false;
89275
88922
  } catch (err2) {
89276
- console.log(
88923
+ logWithTimestamp(
89277
88924
  `[okx-agent-task:${myXmtpAddress}] checkSensitiveWord errored, letting message through:`,
89278
88925
  err2
89279
88926
  );
@@ -89286,31 +88933,44 @@ async function verifyInboundA2AGroupMessage(params) {
89286
88933
  conversationId: groupId,
89287
88934
  messageId,
89288
88935
  stage: "inbound/sensitive_check",
89289
- reason: "exception"
88936
+ reason: "exception",
88937
+ ...timing?.extras()
89290
88938
  });
89291
88939
  }
89292
88940
  return true;
89293
88941
  }
89294
88942
  async function processFileMessage(ctx, deps, options = {}) {
89295
88943
  const messageId = ctx.message.id ?? "";
88944
+ const timing = createInboundTimingTracker(extractXmtpSentAtMs2(ctx.message));
89296
88945
  if (messageId && !tryMarkProcessed(messageId)) {
89297
- console.log(`[okx-agent-task:${deps.myXmtpAddress}] duplicate message ignored: ${messageId}`);
88946
+ logWithTimestamp(`[okx-agent-task:${deps.myXmtpAddress}] duplicate message ignored: ${messageId}`);
89298
88947
  return false;
89299
88948
  }
89300
88949
  const { chatType, conversationId } = getConversationInfo(ctx.conversation);
88950
+ const commonDeliveryExtras = (extra = {}) => timing.extras({
88951
+ ...agentExtras({ walletAddress: deps.myXmtpAddress }),
88952
+ conversationId,
88953
+ messageId,
88954
+ chatType,
88955
+ ...extra
88956
+ });
89301
88957
  if (chatType === "dm") {
88958
+ const dmTrustStartedAt = Date.now();
89302
88959
  const trusted = await isTrustedDmSender({
89303
88960
  myXmtpAddress: deps.myXmtpAddress,
89304
88961
  senderInboxId: ctx.message.senderInboxId ?? "",
89305
88962
  messageId,
89306
88963
  conversationId
89307
88964
  });
88965
+ timing.mark("dmTrustCheck", dmTrustStartedAt);
89308
88966
  if (!trusted) {
89309
88967
  return true;
89310
88968
  }
89311
88969
  }
88970
+ const parseStartedAt = Date.now();
89312
88971
  const rawText = extractRawText(ctx.message.content);
89313
88972
  const parsed = parsePayload(rawText);
88973
+ timing.mark("payloadParse", parseStartedAt);
89314
88974
  const systemNotification = chatType === "dm" && parsed.parsed ? extractSystemNotification(parsed.payload) : null;
89315
88975
  if (systemNotification) {
89316
88976
  const systemMessageId = messageId || `system-${(0, import_node_crypto9.randomUUID)()}`;
@@ -89326,7 +88986,7 @@ async function processFileMessage(ctx, deps, options = {}) {
89326
88986
  reason: "system_dm_missing_agent_id"
89327
88987
  }
89328
88988
  );
89329
- console.log(
88989
+ logWithTimestamp(
89330
88990
  `[okx-agent-task:${deps.myXmtpAddress}] system DM missing agentId, dropping message=${shortenLogValue(systemMessageId)}`
89331
88991
  );
89332
88992
  return true;
@@ -89344,28 +89004,59 @@ async function processFileMessage(ctx, deps, options = {}) {
89344
89004
  reason: "invalid_direct_communication_payload"
89345
89005
  }
89346
89006
  );
89347
- console.log(
89007
+ logWithTimestamp(
89348
89008
  `[okx-agent-task:${deps.myXmtpAddress}] invalid direct communication system DM, dropping message=${shortenLogValue(systemMessageId)}`
89349
89009
  );
89350
89010
  return true;
89351
89011
  }
89012
+ const providerBindStartedAt = Date.now();
89352
89013
  const providerGate = bindMessageJobProviderToCurrentDefault(deps, systemNotification.jobId, "system-notification");
89014
+ timing.mark("providerBind", providerBindStartedAt);
89353
89015
  if (!providerGate.allowed) {
89354
89016
  return true;
89355
89017
  }
89018
+ logger.info(LogEvent.SYSTEM_NOTIFICATION_RECEIVED, {
89019
+ ...agentExtras({ walletAddress: deps.myXmtpAddress, onchainosAgentId: systemNotification.agentId }),
89020
+ taskId: systemNotification.jobId ?? "",
89021
+ agentId: systemNotification.agentId ?? "",
89022
+ providerAgentId: systemNotification.providerAgentId ?? "",
89023
+ clientAgentId: systemNotification.clientAgentId ?? "",
89024
+ messageId: systemMessageId,
89025
+ systemEvent: systemNotification.event ?? "",
89026
+ stage: "inbound/system_notification_received",
89027
+ isDirectCommunication: String(systemNotification.isDirectCommunication),
89028
+ providerBinding: providerGate.provider ?? "",
89029
+ providerBindingCreated: String(providerGate.created)
89030
+ });
89031
+ const routeResolveStartedAt = Date.now();
89356
89032
  const targets = directTarget ? [{
89357
89033
  sessionKey: directTarget.sessionKey,
89358
89034
  route: "job",
89359
89035
  jobId: directTarget.jobId,
89360
89036
  agentId: directTarget.myAgentId
89361
89037
  }] : resolveSystemNotificationTargets(deps, systemNotification);
89038
+ timing.mark("routeResolve", routeResolveStartedAt);
89362
89039
  if (directTarget) {
89363
89040
  upsertDirectCommunicationSession(deps, directTarget);
89364
- console.log(
89041
+ logWithTimestamp(
89365
89042
  `[okx-agent-task:${deps.myXmtpAddress}] direct communication session prepared session=${directTarget.sessionKey} job=${shortenLogValue(directTarget.jobId)} myAgent=${directTarget.myAgentId} toAgent=${directTarget.toAgentId}`
89366
89043
  );
89367
89044
  }
89368
89045
  const primaryTarget = targets[0];
89046
+ logger.info(LogEvent.SYSTEM_NOTIFICATION_ROUTED, {
89047
+ ...agentExtras({ walletAddress: deps.myXmtpAddress, onchainosAgentId: systemNotification.agentId }),
89048
+ taskId: systemNotification.jobId ?? "",
89049
+ agentId: primaryTarget?.agentId ?? systemNotification.agentId ?? "",
89050
+ providerAgentId: systemNotification.providerAgentId ?? "",
89051
+ clientAgentId: systemNotification.clientAgentId ?? "",
89052
+ messageId: systemMessageId,
89053
+ sessionKey: primaryTarget?.sessionKey ?? SYSTEM_NOTIFICATION_SESSION_KEY,
89054
+ route: primaryTarget ? `system/${primaryTarget.route}` : "system/none",
89055
+ targetCount: String(targets.length),
89056
+ systemEvent: systemNotification.event ?? "",
89057
+ stage: "inbound/system_notification_routed",
89058
+ isDirectCommunication: String(systemNotification.isDirectCommunication)
89059
+ });
89369
89060
  if (!options.skipNotify) {
89370
89061
  maybeNotifyInboundAgentMessage({
89371
89062
  deps,
@@ -89377,24 +89068,40 @@ async function processFileMessage(ctx, deps, options = {}) {
89377
89068
  });
89378
89069
  }
89379
89070
  for (const target of targets) {
89071
+ const dispatchStartedAt = Date.now();
89380
89072
  void Promise.resolve(deps.onSessionMessage?.({
89381
89073
  sessionKey: target.sessionKey,
89382
89074
  content: rawText,
89383
89075
  messageId: systemMessageId,
89384
89076
  jobId: target.jobId ?? null,
89385
89077
  agentId: target.agentId ?? null
89386
- })).catch((err2) => {
89387
- console.log(`[okx-agent-task:${deps.myXmtpAddress}] onSessionMessage failed:`, err2);
89078
+ })).then(() => {
89079
+ timing.mark("sessionDispatch", dispatchStartedAt);
89080
+ logger.info(LogEvent.INBOUND_DELIVERED, commonDeliveryExtras({
89081
+ taskId: target.jobId ?? "",
89082
+ agentId: target.agentId ?? "",
89083
+ sessionKey: target.sessionKey,
89084
+ messageId: systemMessageId,
89085
+ route: `system/${target.route}`,
89086
+ stage: "inbound/system_session_dispatch",
89087
+ dispatchTarget: deps.onSessionMessage ? "session" : "none"
89088
+ }));
89089
+ }).catch((err2) => {
89090
+ logWithTimestamp(`[okx-agent-task:${deps.myXmtpAddress}] onSessionMessage failed:`, err2);
89388
89091
  });
89389
- console.log(
89092
+ logWithTimestamp(
89390
89093
  `[okx-agent-task:${deps.myXmtpAddress}] session dispatch queued route=system/${target.route} session=${target.sessionKey} message=${shortenLogValue(systemMessageId)} ${summarizePayloadForLog(parsed.payload)}`
89391
89094
  );
89392
89095
  }
89393
89096
  return true;
89394
89097
  }
89098
+ const routeStartedAt = Date.now();
89395
89099
  const route = routeMessage(chatType, parsed.parsed, parsed.payload);
89100
+ timing.mark("routeResolve", routeStartedAt);
89396
89101
  if (route.route === "job") {
89102
+ const providerBindStartedAt = Date.now();
89397
89103
  const providerGate = bindMessageJobProviderToCurrentDefault(deps, route.jobId, "inbound-xmtp");
89104
+ timing.mark("providerBind", providerBindStartedAt);
89398
89105
  if (!providerGate.allowed) {
89399
89106
  return true;
89400
89107
  }
@@ -89404,12 +89111,14 @@ async function processFileMessage(ctx, deps, options = {}) {
89404
89111
  payload: parsed.parsed ? parsed.payload : null,
89405
89112
  myXmtpAddress: deps.myXmtpAddress
89406
89113
  }) : null;
89407
- const xmtpSentAtMs = extractXmtpSentAtMs(ctx.message);
89114
+ const xmtpSentAtMs = extractXmtpSentAtMs2(ctx.message);
89408
89115
  let senderAddress = "";
89409
89116
  try {
89117
+ const senderStartedAt = Date.now();
89410
89118
  senderAddress = await ctx.getSenderAddress();
89119
+ timing.mark("senderResolve", senderStartedAt);
89411
89120
  } catch (err2) {
89412
- console.log(
89121
+ logWithTimestamp(
89413
89122
  `[okx-agent-task:${deps.myXmtpAddress}] getSenderAddress failed for ${messageId || "(no-id)"}:`,
89414
89123
  err2
89415
89124
  );
@@ -89422,7 +89131,7 @@ async function processFileMessage(ctx, deps, options = {}) {
89422
89131
  senderInboxId: ctx.message.senderInboxId ?? ""
89423
89132
  });
89424
89133
  if (payloadObject?.msgType !== A2A_MESSAGE_TYPE && !trustedSystemSender) {
89425
- console.log(
89134
+ logWithTimestamp(
89426
89135
  `[okx-agent-task:${deps.myXmtpAddress}] group message unsupported msgType, dropping: msgType=${String(payloadObject?.msgType ?? "(missing)")} job=${shortenLogValue(route.jobId)} group=${conversationId}`
89427
89136
  );
89428
89137
  logger.info(LogEvent.INBOUND_DROP_UNSUPPORTED_MSGTYPE, {
@@ -89436,7 +89145,8 @@ async function processFileMessage(ctx, deps, options = {}) {
89436
89145
  msgType: readString3(payloadObject?.msgType) ?? "",
89437
89146
  msgTypeType: typeof payloadObject?.msgType,
89438
89147
  stage: "inbound/payload_parse",
89439
- reason: "unsupported_msg_type"
89148
+ reason: "unsupported_msg_type",
89149
+ ...timing.extras()
89440
89150
  });
89441
89151
  return true;
89442
89152
  }
@@ -89453,7 +89163,8 @@ async function processFileMessage(ctx, deps, options = {}) {
89453
89163
  groupId: conversationId,
89454
89164
  messageId,
89455
89165
  consentState: ctx.conversation instanceof Group ? ctx.conversation.consentState : void 0,
89456
- trustedSystemSender
89166
+ trustedSystemSender,
89167
+ timing
89457
89168
  });
89458
89169
  if (!accepted) {
89459
89170
  return true;
@@ -89471,7 +89182,7 @@ async function processFileMessage(ctx, deps, options = {}) {
89471
89182
  localAgentRole: localAgent?.role ?? null,
89472
89183
  hasExistingSession: !!existingSession
89473
89184
  })) {
89474
- console.log(
89185
+ logWithTimestamp(
89475
89186
  `[okx-agent-task:${deps.myXmtpAddress}] buyer inbound group kept pending: session=${sessionKey} job=${shortenLogValue(route.jobId)} group=${conversationId} consent=${String(consentState)} message=${shortenLogValue(routedMessageId)}`
89476
89187
  );
89477
89188
  logger.info(LogEvent.INBOUND_BUYER_PENDING, {
@@ -89484,7 +89195,8 @@ async function processFileMessage(ctx, deps, options = {}) {
89484
89195
  messageId: routedMessageId,
89485
89196
  consentState: String(consentState),
89486
89197
  stage: "inbound/buyer_pending",
89487
- reason: "unknown_group_without_session"
89198
+ reason: "unknown_group_without_session",
89199
+ ...timing.extras()
89488
89200
  });
89489
89201
  if (!options.skipNotify) {
89490
89202
  notifyPendingConversationToBackup({
@@ -89500,7 +89212,7 @@ async function processFileMessage(ctx, deps, options = {}) {
89500
89212
  idempotencyKey: `pending-conversation:${conversationId}`,
89501
89213
  store: deps.sessionStore
89502
89214
  }).catch((err2) => {
89503
- console.log(`[okx-agent-task:${deps.myXmtpAddress}] pending conversation user notification failed:`, err2);
89215
+ logWithTimestamp(`[okx-agent-task:${deps.myXmtpAddress}] pending conversation user notification failed:`, err2);
89504
89216
  });
89505
89217
  }
89506
89218
  return true;
@@ -89514,14 +89226,29 @@ async function processFileMessage(ctx, deps, options = {}) {
89514
89226
  myAgentXmtpAddress: deps.myXmtpAddress,
89515
89227
  toAgentXmtpAddress: senderAddress || null
89516
89228
  });
89229
+ const dispatchStartedAt = Date.now();
89517
89230
  void Promise.resolve(deps.onSessionMessage?.({
89518
89231
  sessionKey,
89519
89232
  content: rawText,
89520
89233
  messageId: routedMessageId,
89521
89234
  jobId: route.jobId,
89522
89235
  agentId: myAgentId
89523
- })).catch((err2) => {
89524
- console.log(`[okx-agent-task:${deps.myXmtpAddress}] onSessionMessage failed:`, err2);
89236
+ })).then(() => {
89237
+ timing.mark("sessionDispatch", dispatchStartedAt);
89238
+ logger.info(LogEvent.INBOUND_DELIVERED, commonDeliveryExtras({
89239
+ taskId: route.jobId,
89240
+ agentId: myAgentId ?? "",
89241
+ peerWalletAddress: senderAddress,
89242
+ peerInboxId: ctx.message.senderInboxId ?? "",
89243
+ peerAgentId: toAgentId ?? "",
89244
+ sessionKey,
89245
+ messageId: routedMessageId,
89246
+ route: "group",
89247
+ stage: "inbound/group_session_dispatch",
89248
+ dispatchTarget: deps.onSessionMessage ? "session" : "none"
89249
+ }));
89250
+ }).catch((err2) => {
89251
+ logWithTimestamp(`[okx-agent-task:${deps.myXmtpAddress}] onSessionMessage failed:`, err2);
89525
89252
  });
89526
89253
  if (!options.skipNotify) {
89527
89254
  maybeNotifyInboundAgentMessage({
@@ -89535,7 +89262,7 @@ async function processFileMessage(ctx, deps, options = {}) {
89535
89262
  });
89536
89263
  }
89537
89264
  void maybeAllowProviderGroup(deps, chatType, conversationId);
89538
- console.log(
89265
+ logWithTimestamp(
89539
89266
  `[okx-agent-task:${deps.myXmtpAddress}] session dispatch queued route=group session=${sessionKey} message=${shortenLogValue(routedMessageId)} ${summarizePayloadForLog(parsed.payload)}`
89540
89267
  );
89541
89268
  return true;
@@ -89555,7 +89282,9 @@ async function processFileMessage(ctx, deps, options = {}) {
89555
89282
  rawText,
89556
89283
  payload: parsed.parsed ? parsed.payload : null
89557
89284
  };
89285
+ const storeAppendStartedAt = Date.now();
89558
89286
  await deps.store.append(route.jobId, stored, sessionAgentId);
89287
+ timing.mark("storeAppend", storeAppendStartedAt);
89559
89288
  if ((route.route === "job" || parsed.parsed && !isA2AEnvelope(stored.payload)) && !options.skipNotify) {
89560
89289
  const payloadObject = isPlainObject3(stored.payload) ? stored.payload : null;
89561
89290
  const sender = isPlainObject3(payloadObject?.sender) ? payloadObject.sender : null;
@@ -89588,17 +89317,31 @@ async function processFileMessage(ctx, deps, options = {}) {
89588
89317
  }
89589
89318
  if (route.route === "job" && !options.skipAi) {
89590
89319
  const jobFilePath = deps.store.jobFilePath(route.jobId, sessionAgentId);
89320
+ const dispatchStartedAt = Date.now();
89591
89321
  void Promise.resolve(deps.onJobMessageStored?.({
89592
89322
  jobId: route.jobId,
89593
89323
  jobFilePath,
89594
89324
  sessionAgentId,
89595
89325
  message: stored
89596
- })).catch((err2) => {
89597
- console.log(`[okx-agent-task:${deps.myXmtpAddress}] onJobMessageStored failed:`, err2);
89326
+ })).then(() => {
89327
+ timing.mark("jobDispatch", dispatchStartedAt);
89328
+ logger.info(LogEvent.INBOUND_DELIVERED, commonDeliveryExtras({
89329
+ taskId: route.jobId,
89330
+ peerWalletAddress: senderAddress,
89331
+ peerInboxId: ctx.message.senderInboxId ?? "",
89332
+ sessionAgentId: sessionAgentId ?? "",
89333
+ messageId: stored.id,
89334
+ route: route.route,
89335
+ routeReason: route.routeReason,
89336
+ stage: "inbound/job_store_dispatch",
89337
+ dispatchTarget: deps.onJobMessageStored ? "job" : "none"
89338
+ }));
89339
+ }).catch((err2) => {
89340
+ logWithTimestamp(`[okx-agent-task:${deps.myXmtpAddress}] onJobMessageStored failed:`, err2);
89598
89341
  });
89599
89342
  }
89600
89343
  void maybeAllowProviderGroup(deps, chatType, conversationId);
89601
- console.log(
89344
+ logWithTimestamp(
89602
89345
  `[okx-agent-task:${deps.myXmtpAddress}] stored ${chatType} message route=${route.route} job=${shortenLogValue(route.jobId)} reason=${route.routeReason} message=${shortenLogValue(stored.id)} ${summarizePayloadForLog(stored.payload)}`
89603
89346
  );
89604
89347
  return true;
@@ -89606,16 +89349,34 @@ async function processFileMessage(ctx, deps, options = {}) {
89606
89349
  function createFileMessageHandler(deps) {
89607
89350
  return async (ctx, _next) => {
89608
89351
  const msg = ctx.message;
89352
+ const inboundCtx = ctx;
89353
+ const xmtpReceivedAtMs = Date.now();
89354
+ const xmtpSentAtMs = extractXmtpSentAtMs2(inboundCtx.message);
89355
+ const { chatType, conversationId } = getConversationInfo(ctx.conversation);
89356
+ logger.info(LogEvent.INBOUND_HANDLER_ENTERED, {
89357
+ ...agentExtras({ walletAddress: deps.myXmtpAddress }),
89358
+ ...jobIdExtras(inboundCtx.message.content),
89359
+ source: "live",
89360
+ stage: "inbound/handler_entered",
89361
+ chatType,
89362
+ conversationId,
89363
+ messageId: inboundCtx.message.id ?? "",
89364
+ kind: msg.kind ?? "unknown",
89365
+ senderInboxId: inboundCtx.message.senderInboxId ?? "",
89366
+ xmtpSentAtMs: String(xmtpSentAtMs),
89367
+ xmtpReceivedAtMs: String(xmtpReceivedAtMs),
89368
+ xmtpDeliveryMs: String(safeDuration(xmtpReceivedAtMs, xmtpSentAtMs))
89369
+ });
89609
89370
  if (msg.kind && msg.kind !== "application") {
89610
89371
  return;
89611
89372
  }
89612
89373
  try {
89613
89374
  const handled = await processFileMessage(ctx, deps);
89614
89375
  if (handled) {
89615
- deps.onMessageProcessed?.(extractXmtpSentAtMs(ctx.message));
89376
+ deps.onMessageProcessed?.(extractXmtpSentAtMs2(ctx.message));
89616
89377
  }
89617
89378
  } catch (err2) {
89618
- console.log(`[okx-agent-task:${deps.myXmtpAddress}] process message failed:`, err2);
89379
+ logWithTimestamp(`[okx-agent-task:${deps.myXmtpAddress}] process message failed:`, err2);
89619
89380
  }
89620
89381
  };
89621
89382
  }
@@ -89664,7 +89425,7 @@ function isA2AEnvelope(payload) {
89664
89425
 
89665
89426
  // ../core/src/xmtp-sdk/onchainos/signer.ts
89666
89427
  async function onchainosSign(agentId, keyUuid, walletAddress, message) {
89667
- console.log(
89428
+ logWithTimestamp(
89668
89429
  `[onchainos-signer] executing: onchainos agent xmtp-sign --key-uuid ${keyUuid} --message <${message.length} chars>`
89669
89430
  );
89670
89431
  let stdout;
@@ -89686,7 +89447,7 @@ async function onchainosSign(agentId, keyUuid, walletAddress, message) {
89686
89447
  throw err2;
89687
89448
  }
89688
89449
  if (stderr) {
89689
- console.log(`[onchainos-signer] stderr: ${stderr}`);
89450
+ logWithTimestamp(`[onchainos-signer] stderr: ${stderr}`);
89690
89451
  }
89691
89452
  const res = parseCliJson(stdout, "xmtp-sign", {
89692
89453
  onchainosAgentId: agentId,
@@ -89711,7 +89472,7 @@ async function onchainosSign(agentId, keyUuid, walletAddress, message) {
89711
89472
  );
89712
89473
  throw signErr;
89713
89474
  }
89714
- console.log(
89475
+ logWithTimestamp(
89715
89476
  `[onchainos-signer] sign success, signature=${res.data.signature.slice(0, 20)}...`
89716
89477
  );
89717
89478
  return toBytes(res.data.signature);
@@ -89720,7 +89481,7 @@ function createOnchainosSigner(agent) {
89720
89481
  const address = agent.communicationAddress.toLowerCase();
89721
89482
  const keyUuid = agent.keyUuid;
89722
89483
  const agentId = agent.agentId;
89723
- console.log(
89484
+ logWithTimestamp(
89724
89485
  `[onchainos-signer] creating signer for ${address} (keyUuid=${keyUuid})`
89725
89486
  );
89726
89487
  return {
@@ -89730,7 +89491,7 @@ function createOnchainosSigner(agent) {
89730
89491
  identifierKind: 0
89731
89492
  }),
89732
89493
  signMessage: async (message) => {
89733
- console.log(`[onchainos-signer] signing message for ${address}`);
89494
+ logWithTimestamp(`[onchainos-signer] signing message for ${address}`);
89734
89495
  return await onchainosSign(agentId, keyUuid, address, message);
89735
89496
  }
89736
89497
  };
@@ -89888,10 +89649,545 @@ function userWatchEventDeliveredSentryExtra(event) {
89888
89649
  var environment = process.env.SENTRY_ENV === "dev" ? "dev" : "prod";
89889
89650
  var SENTRY_CONFIG = {
89890
89651
  projectName: "okx/openclaw-okx-a2a-extension",
89891
- release: "0.0.13-beta-d0ec14bc63-260622192924",
89652
+ release: "0.0.13",
89892
89653
  environment
89893
89654
  };
89894
89655
 
89656
+ // src/forced-update.ts
89657
+ var import_node_child_process7 = require("node:child_process");
89658
+
89659
+ // src/update-cli.ts
89660
+ var import_node_child_process6 = require("node:child_process");
89661
+ var import_promises6 = require("node:fs/promises");
89662
+ var import_node_os5 = require("node:os");
89663
+ var import_node_path17 = require("node:path");
89664
+ var UPDATE_PACKAGES = {
89665
+ node: "@okxweb3/a2a-node",
89666
+ openclaw: "@okxweb3/a2a-openclaw",
89667
+ hermes: "@okxweb3/a2a-hermes"
89668
+ };
89669
+ function isPrereleaseVersion(version2) {
89670
+ return /\d+\.\d+\.\d+-[0-9A-Za-z.-]+/.test(version2);
89671
+ }
89672
+ async function normalizeHermesOkxA2aPluginConfig(configFile = resolveHermesConfigPath()) {
89673
+ let content3;
89674
+ try {
89675
+ content3 = await (0, import_promises6.readFile)(configFile, "utf8");
89676
+ } catch (error) {
89677
+ if (isNodeError(error) && error.code === "ENOENT") {
89678
+ return false;
89679
+ }
89680
+ throw error;
89681
+ }
89682
+ const normalized = normalizeHermesPluginConfigContent(content3);
89683
+ if (!normalized.changed) {
89684
+ return false;
89685
+ }
89686
+ await (0, import_promises6.writeFile)(configFile, normalized.content);
89687
+ console.log(`[update] normalized Hermes plugins.enabled okx-a2a entry in ${configFile}`);
89688
+ return true;
89689
+ }
89690
+ function normalizeHermesPluginConfigContent(content3) {
89691
+ const trailingNewline = content3.endsWith("\n");
89692
+ const duplicateRepair = removeDuplicateInlineEnabledHeaders(content3.replace(/\n$/, "").split(/\n/));
89693
+ const lines = duplicateRepair.lines;
89694
+ let changed = duplicateRepair.changed;
89695
+ let hasOkxA2a = false;
89696
+ let inPlugins = false;
89697
+ let pluginsIndent = -1;
89698
+ let inEnabled = false;
89699
+ let enabledIndent = -1;
89700
+ let emittedOkxA2a = false;
89701
+ const output = [];
89702
+ for (const line of lines) {
89703
+ const currentIndent = lineIndent(line);
89704
+ const significant = line.trim() !== "" && !line.trimStart().startsWith("#");
89705
+ const parsedListValue = parseYamlListValue(line);
89706
+ if (inEnabled && significant && (currentIndent < enabledIndent || currentIndent === enabledIndent && !parsedListValue)) {
89707
+ inEnabled = false;
89708
+ emittedOkxA2a = false;
89709
+ }
89710
+ if (inPlugins && significant && currentIndent <= pluginsIndent && !isPluginsHeader(line)) {
89711
+ inPlugins = false;
89712
+ inEnabled = false;
89713
+ emittedOkxA2a = false;
89714
+ }
89715
+ if (isPluginsHeader(line)) {
89716
+ inPlugins = true;
89717
+ pluginsIndent = currentIndent;
89718
+ output.push(line);
89719
+ continue;
89720
+ }
89721
+ if (inPlugins && isEnabledHeader(line) && currentIndent > pluginsIndent) {
89722
+ inEnabled = true;
89723
+ enabledIndent = currentIndent;
89724
+ emittedOkxA2a = false;
89725
+ output.push(line);
89726
+ continue;
89727
+ }
89728
+ const inlineEnabled = inPlugins ? parseInlineEnabledList(line) : null;
89729
+ if (inlineEnabled && currentIndent > pluginsIndent) {
89730
+ const normalized = normalizeInlineEnabledList(inlineEnabled);
89731
+ output.push(...normalized.lines);
89732
+ changed ||= normalized.changed;
89733
+ hasOkxA2a ||= normalized.hasOkxA2a;
89734
+ continue;
89735
+ }
89736
+ if (inEnabled) {
89737
+ const parsed = parsedListValue;
89738
+ if (parsed && (parsed.value === "okx-a2a" || parsed.value === "platforms/okx-a2a")) {
89739
+ hasOkxA2a = true;
89740
+ if (!emittedOkxA2a) {
89741
+ const normalized = `${parsed.indent}- okx-a2a`;
89742
+ output.push(normalized);
89743
+ changed ||= normalized !== line;
89744
+ emittedOkxA2a = true;
89745
+ } else {
89746
+ changed = true;
89747
+ }
89748
+ continue;
89749
+ }
89750
+ }
89751
+ output.push(line);
89752
+ }
89753
+ return { content: `${output.join("\n")}${trailingNewline ? "\n" : ""}`, changed, hasOkxA2a };
89754
+ }
89755
+ function removeDuplicateInlineEnabledHeaders(lines) {
89756
+ let changed = false;
89757
+ let inPlugins = false;
89758
+ let pluginsIndent = -1;
89759
+ const output = [];
89760
+ for (let i = 0; i < lines.length; i++) {
89761
+ const line = lines[i];
89762
+ const currentIndent = lineIndent(line);
89763
+ const significant = line.trim() !== "" && !line.trimStart().startsWith("#");
89764
+ if (inPlugins && significant && currentIndent <= pluginsIndent && !isPluginsHeader(line)) {
89765
+ inPlugins = false;
89766
+ }
89767
+ if (isPluginsHeader(line)) {
89768
+ inPlugins = true;
89769
+ pluginsIndent = currentIndent;
89770
+ output.push(line);
89771
+ continue;
89772
+ }
89773
+ if (inPlugins && isEmptyInlineEnabledList(line) && hasLaterEnabledHeaderInPlugins(lines, i + 1, pluginsIndent)) {
89774
+ changed = true;
89775
+ continue;
89776
+ }
89777
+ output.push(line);
89778
+ }
89779
+ return { lines: output, changed };
89780
+ }
89781
+ function hasLaterEnabledHeaderInPlugins(lines, startIndex, pluginsIndent) {
89782
+ for (let i = startIndex; i < lines.length; i++) {
89783
+ const line = lines[i];
89784
+ const significant = line.trim() !== "" && !line.trimStart().startsWith("#");
89785
+ if (significant && lineIndent(line) <= pluginsIndent) {
89786
+ return false;
89787
+ }
89788
+ if (isEnabledHeader(line) || parseInlineEnabledList(line)) {
89789
+ return true;
89790
+ }
89791
+ }
89792
+ return false;
89793
+ }
89794
+ function isEmptyInlineEnabledList(line) {
89795
+ const inline = parseInlineEnabledList(line);
89796
+ return !!inline && inline.values.length === 0;
89797
+ }
89798
+ function resolveHermesConfigPath() {
89799
+ return (0, import_node_path17.join)(process.env.HERMES_HOME ?? (0, import_node_path17.join)((0, import_node_os5.homedir)(), ".hermes"), "config.yaml");
89800
+ }
89801
+ function lineIndent(line) {
89802
+ const match = line.match(/^\s*/);
89803
+ return match?.[0].length ?? 0;
89804
+ }
89805
+ function isPluginsHeader(line) {
89806
+ return /^[\s]*plugins:[\s]*(?:#.*)?$/.test(line);
89807
+ }
89808
+ function isEnabledHeader(line) {
89809
+ return /^[\s]*enabled:[\s]*(?:#.*)?$/.test(line);
89810
+ }
89811
+ function parseInlineEnabledList(line) {
89812
+ const match = line.match(/^(\s*)enabled:\s*\[(.*)\]\s*(?:#.*)?$/);
89813
+ if (!match) {
89814
+ return null;
89815
+ }
89816
+ const values = (match[2] ?? "").split(",").map((value) => value.trim().replace(/^["']|["']$/g, "")).filter(Boolean);
89817
+ return { indent: match[1] ?? "", values };
89818
+ }
89819
+ function normalizeInlineEnabledList(input) {
89820
+ let hasOkxA2a = false;
89821
+ const values = [];
89822
+ for (const value of input.values) {
89823
+ if (value === "okx-a2a" || value === "platforms/okx-a2a") {
89824
+ hasOkxA2a = true;
89825
+ if (!values.includes("okx-a2a")) {
89826
+ values.push("okx-a2a");
89827
+ }
89828
+ continue;
89829
+ }
89830
+ values.push(value);
89831
+ }
89832
+ return {
89833
+ lines: values.length > 0 ? [`${input.indent}enabled:`, ...values.map((value) => `${input.indent} - ${value}`)] : [`${input.indent}enabled: []`],
89834
+ changed: hasOkxA2a,
89835
+ hasOkxA2a
89836
+ };
89837
+ }
89838
+ function parseYamlListValue(line) {
89839
+ const match = line.match(/^(\s*)-\s*(?:"([^"]*)"|'([^']*)'|([^#\s]+))(?:\s*(?:#.*)?)?$/);
89840
+ if (!match) {
89841
+ return null;
89842
+ }
89843
+ return {
89844
+ indent: match[1] ?? "",
89845
+ value: match[2] ?? match[3] ?? match[4] ?? ""
89846
+ };
89847
+ }
89848
+ function isNodeError(error) {
89849
+ return error instanceof Error && "code" in error;
89850
+ }
89851
+ async function getInstalledGatewayPluginVersion(target) {
89852
+ if (target === "hermes") {
89853
+ return await getInstalledHermesPluginVersion() ?? await getGlobalNpmPackageVersion(UPDATE_PACKAGES.hermes);
89854
+ }
89855
+ return (await getInstalledOpenClawPluginInfo()).version;
89856
+ }
89857
+ async function getInstalledOpenClawPluginInfo() {
89858
+ let result = await runCommandCaptureOptional("openclaw", ["plugins", "list", "--json"]);
89859
+ if (!result.ok) {
89860
+ result = await runCommandCaptureOptional("openclaw", ["plugins", "list"]);
89861
+ }
89862
+ if (!result.ok) {
89863
+ return { installed: false, version: null };
89864
+ }
89865
+ return parseOpenClawPluginList(result.stdout);
89866
+ }
89867
+ function parseOpenClawPluginList(output) {
89868
+ if (!output.trim()) {
89869
+ return { installed: false, version: null };
89870
+ }
89871
+ try {
89872
+ return findOpenClawPluginInJson(JSON.parse(output));
89873
+ } catch {
89874
+ return {
89875
+ installed: output.includes(UPDATE_PACKAGES.openclaw) || /(^|[\s@/])okx-a2a($|[\s@])/.test(output),
89876
+ version: parsePackageVersionFromText(output)
89877
+ };
89878
+ }
89879
+ }
89880
+ function findOpenClawPluginInJson(value) {
89881
+ if (Array.isArray(value)) {
89882
+ for (const item of value) {
89883
+ const found = findOpenClawPluginInJson(item);
89884
+ if (found.installed) {
89885
+ return found;
89886
+ }
89887
+ }
89888
+ return { installed: false, version: null };
89889
+ }
89890
+ if (!value || typeof value !== "object") {
89891
+ return { installed: false, version: null };
89892
+ }
89893
+ const record = value;
89894
+ if (isOpenClawPluginRecord(record)) {
89895
+ return { installed: true, version: readVersionField(record) };
89896
+ }
89897
+ const dependencies = record.dependencies;
89898
+ if (dependencies && typeof dependencies === "object") {
89899
+ const dependency = dependencies[UPDATE_PACKAGES.openclaw] ?? dependencies["okx-a2a"];
89900
+ if (dependency && typeof dependency === "object") {
89901
+ return { installed: true, version: readVersionField(dependency) };
89902
+ }
89903
+ }
89904
+ for (const key of ["plugins", "items", "data", "installed"]) {
89905
+ const child = record[key];
89906
+ if (child !== void 0) {
89907
+ const found = findOpenClawPluginInJson(child);
89908
+ if (found.installed) {
89909
+ return found;
89910
+ }
89911
+ }
89912
+ }
89913
+ return { installed: false, version: null };
89914
+ }
89915
+ function isOpenClawPluginRecord(record) {
89916
+ return Object.values(record).some((value) => {
89917
+ if (typeof value !== "string") {
89918
+ return false;
89919
+ }
89920
+ return value === "okx-a2a" || value === UPDATE_PACKAGES.openclaw || value.endsWith("/okx-a2a");
89921
+ });
89922
+ }
89923
+ function readVersionField(record) {
89924
+ for (const key of ["version", "installedVersion", "packageVersion"]) {
89925
+ const value = record[key];
89926
+ if (typeof value === "string" && value.trim()) {
89927
+ return value.trim();
89928
+ }
89929
+ }
89930
+ return null;
89931
+ }
89932
+ function parsePackageVersionFromText(output) {
89933
+ return output.match(/@okxweb3\/a2a-openclaw@([0-9A-Za-z.+-]+)/)?.[1] ?? null;
89934
+ }
89935
+ async function getInstalledHermesPluginVersion() {
89936
+ const pluginYaml = (0, import_node_path17.join)(process.env.HERMES_HOME ?? (0, import_node_path17.join)((0, import_node_os5.homedir)(), ".hermes"), "plugins", "platforms", "okx-a2a", "plugin.yaml");
89937
+ try {
89938
+ const content3 = await (0, import_promises6.readFile)(pluginYaml, "utf8");
89939
+ return parsePluginYamlVersion(content3);
89940
+ } catch (error) {
89941
+ if (isNodeError(error) && error.code === "ENOENT") {
89942
+ return null;
89943
+ }
89944
+ throw error;
89945
+ }
89946
+ }
89947
+ function parsePluginYamlVersion(content3) {
89948
+ for (const line of content3.split(/\r?\n/)) {
89949
+ const match = line.match(/^\s*version:\s*(?:"([^"]+)"|'([^']+)'|([^#\s]+))/);
89950
+ if (match) {
89951
+ return match[1] ?? match[2] ?? match[3] ?? null;
89952
+ }
89953
+ }
89954
+ return null;
89955
+ }
89956
+ async function getGlobalNpmPackageVersion(packageName) {
89957
+ const result = await runCommandCaptureOptional("npm", ["list", "-g", packageName, "--depth=0", "--json"]);
89958
+ if (!result.ok) {
89959
+ return null;
89960
+ }
89961
+ try {
89962
+ const parsed = JSON.parse(result.stdout);
89963
+ return parsed.dependencies?.[packageName]?.version ?? null;
89964
+ } catch {
89965
+ return null;
89966
+ }
89967
+ }
89968
+ async function runCommandCaptureOptional(command, args) {
89969
+ return await new Promise((resolvePromise) => {
89970
+ const child = (0, import_node_child_process6.spawn)(command, args, { stdio: ["ignore", "pipe", "ignore"] });
89971
+ let stdout = "";
89972
+ child.stdout.setEncoding("utf8");
89973
+ child.stdout.on("data", (chunk) => {
89974
+ stdout += chunk;
89975
+ });
89976
+ child.on("error", () => {
89977
+ resolvePromise({ ok: false, stdout });
89978
+ });
89979
+ child.on("close", (code2) => {
89980
+ resolvePromise({ ok: code2 === 0, stdout });
89981
+ });
89982
+ });
89983
+ }
89984
+
89985
+ // src/forced-update.ts
89986
+ var SEMVER_RE2 = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*)?$/;
89987
+ function normalizeSemverInput2(value) {
89988
+ return value.trim().replace(/^v/, "");
89989
+ }
89990
+ function parseSemver2(value) {
89991
+ const match = SEMVER_RE2.exec(normalizeSemverInput2(value));
89992
+ if (!match) {
89993
+ return null;
89994
+ }
89995
+ return {
89996
+ major: Number(match[1]),
89997
+ minor: Number(match[2]),
89998
+ patch: Number(match[3]),
89999
+ prerelease: match[4] ? match[4].split(".") : []
90000
+ };
90001
+ }
90002
+ function comparePrereleaseId2(a, b) {
90003
+ const aIsNumber = /^\d+$/.test(a);
90004
+ const bIsNumber = /^\d+$/.test(b);
90005
+ if (aIsNumber && bIsNumber) {
90006
+ const an = Number(a);
90007
+ const bn = Number(b);
90008
+ return an < bn ? -1 : an > bn ? 1 : 0;
90009
+ }
90010
+ if (aIsNumber) {
90011
+ return -1;
90012
+ }
90013
+ if (bIsNumber) {
90014
+ return 1;
90015
+ }
90016
+ return a < b ? -1 : a > b ? 1 : 0;
90017
+ }
90018
+ function compareSemver2(a, b) {
90019
+ if (a.major !== b.major) {
90020
+ return a.major < b.major ? -1 : 1;
90021
+ }
90022
+ if (a.minor !== b.minor) {
90023
+ return a.minor < b.minor ? -1 : 1;
90024
+ }
90025
+ if (a.patch !== b.patch) {
90026
+ return a.patch < b.patch ? -1 : 1;
90027
+ }
90028
+ if (a.prerelease.length === 0 && b.prerelease.length === 0) {
90029
+ return 0;
90030
+ }
90031
+ if (a.prerelease.length === 0) {
90032
+ return 1;
90033
+ }
90034
+ if (b.prerelease.length === 0) {
90035
+ return -1;
90036
+ }
90037
+ const len = Math.min(a.prerelease.length, b.prerelease.length);
90038
+ for (let i = 0; i < len; i++) {
90039
+ const diff = comparePrereleaseId2(a.prerelease[i], b.prerelease[i]);
90040
+ if (diff !== 0) {
90041
+ return diff;
90042
+ }
90043
+ }
90044
+ if (a.prerelease.length !== b.prerelease.length) {
90045
+ return a.prerelease.length < b.prerelease.length ? -1 : 1;
90046
+ }
90047
+ return 0;
90048
+ }
90049
+ function isBelowRequiredVersion(currentVersion, minVersion) {
90050
+ const min = minVersion?.trim();
90051
+ if (!min) {
90052
+ return false;
90053
+ }
90054
+ const parsedMin = parseSemver2(min);
90055
+ if (!parsedMin) {
90056
+ logWithTimestamp(`[okx-agent-task] ignoring invalid forced minVersion=${min}`);
90057
+ return false;
90058
+ }
90059
+ const current = currentVersion?.trim();
90060
+ if (!current) {
90061
+ return true;
90062
+ }
90063
+ const parsedCurrent = parseSemver2(current);
90064
+ if (!parsedCurrent) {
90065
+ logWithTimestamp(`[okx-agent-task] current version is invalid, forcing update current=${current} min=${min}`);
90066
+ return true;
90067
+ }
90068
+ return compareSemver2(parsedCurrent, parsedMin) < 0;
90069
+ }
90070
+ async function ensureCommunicationMinVersions(input) {
90071
+ const runUpdate = input.runUpdate ?? runOkxA2aForcedUpdate;
90072
+ const cliMinVersion = input.systemConfig.minVersion.cli;
90073
+ const currentCliVersion = input.currentCliVersion ?? "0.0.13";
90074
+ if (isBelowRequiredVersion(currentCliVersion, cliMinVersion)) {
90075
+ await forceUpdate({
90076
+ target: "cli",
90077
+ currentVersion: currentCliVersion,
90078
+ minVersion: cliMinVersion,
90079
+ stage: input.stage,
90080
+ runUpdate
90081
+ });
90082
+ return { updated: true, target: "cli", currentVersion: currentCliVersion, minVersion: cliMinVersion };
90083
+ }
90084
+ const provider = resolveConfiguredAiProvider({ store: input.sessionStore, env: input.env });
90085
+ const gatewayTarget = providerToGatewayTarget(provider);
90086
+ if (!gatewayTarget) {
90087
+ logWithTimestamp(`[okx-agent-task] forced minVersion gateway check skipped provider=${provider ?? "(not set)"}`);
90088
+ return { updated: false };
90089
+ }
90090
+ const minVersion = input.systemConfig.minVersion[gatewayTarget];
90091
+ if (!minVersion) {
90092
+ return { updated: false, target: gatewayTarget };
90093
+ }
90094
+ const getGatewayVersion = input.getGatewayVersion ?? getInstalledGatewayPluginVersion;
90095
+ const currentVersion = await getGatewayVersion(gatewayTarget);
90096
+ if (!isBelowRequiredVersion(currentVersion, minVersion)) {
90097
+ return { updated: false, target: gatewayTarget, currentVersion, minVersion };
90098
+ }
90099
+ await forceUpdate({
90100
+ target: gatewayTarget,
90101
+ currentVersion,
90102
+ minVersion,
90103
+ stage: input.stage,
90104
+ runUpdate
90105
+ });
90106
+ return { updated: true, target: gatewayTarget, currentVersion, minVersion };
90107
+ }
90108
+ function providerToGatewayTarget(provider) {
90109
+ return provider === "openclaw" || provider === "hermes" ? provider : null;
90110
+ }
90111
+ async function forceUpdate(input) {
90112
+ const startedAt = Date.now();
90113
+ logWithTimestamp(
90114
+ `[okx-agent-task] forced update required target=${input.target} current=${input.currentVersion ?? "(unknown)"} min=${input.minVersion} stage=${input.stage}`
90115
+ );
90116
+ logger.info(LogEvent.FORCED_UPDATE_STARTED, forcedUpdateSentryExtra(input, startedAt, {
90117
+ status: "started",
90118
+ reason: "forced_update_required"
90119
+ }));
90120
+ try {
90121
+ await input.runUpdate(input.target);
90122
+ logger.info(LogEvent.FORCED_UPDATE_SUCCEEDED, forcedUpdateSentryExtra(input, startedAt, {
90123
+ status: "succeeded",
90124
+ reason: "update_completed"
90125
+ }));
90126
+ } catch (err2) {
90127
+ const error = err2 instanceof Error ? err2 : new Error(String(err2));
90128
+ logger.error(LogEvent.FORCED_UPDATE_FAILED, error, forcedUpdateSentryExtra(input, startedAt, {
90129
+ status: "failed",
90130
+ reason: "update_failed",
90131
+ errorName: error.name,
90132
+ errorMessage: error.message,
90133
+ errorStack: error.stack ?? "",
90134
+ ...forcedUpdateErrorDetails(err2)
90135
+ }));
90136
+ throw err2;
90137
+ }
90138
+ }
90139
+ function forcedUpdateSentryExtra(input, startedAt, extra) {
90140
+ return {
90141
+ component: "node_listener",
90142
+ stage: input.stage,
90143
+ updateTarget: input.target,
90144
+ currentVersion: input.currentVersion ?? "",
90145
+ minVersion: input.minVersion,
90146
+ durationMs: String(Date.now() - startedAt),
90147
+ ...extra
90148
+ };
90149
+ }
90150
+ function forcedUpdateErrorDetails(err2) {
90151
+ if (!err2 || typeof err2 !== "object") {
90152
+ return {};
90153
+ }
90154
+ const record = err2;
90155
+ return {
90156
+ exitCode: record.exitCode ?? record.code ?? "",
90157
+ signal: record.signal ?? ""
90158
+ };
90159
+ }
90160
+ function runOkxA2aForcedUpdate(target) {
90161
+ const args = [
90162
+ "update",
90163
+ ...target === "cli" ? [] : [target],
90164
+ "--release",
90165
+ "latest",
90166
+ "--restart",
90167
+ "--yes"
90168
+ ];
90169
+ return new Promise((resolvePromise, reject) => {
90170
+ const child = (0, import_node_child_process7.spawn)("okx-a2a", args, {
90171
+ stdio: "inherit",
90172
+ env: {
90173
+ ...process.env,
90174
+ OKX_A2A_FORCED_UPDATE_TARGET: target
90175
+ }
90176
+ });
90177
+ child.on("error", reject);
90178
+ child.on("close", (code2, signal) => {
90179
+ if (code2 === 0) {
90180
+ resolvePromise();
90181
+ return;
90182
+ }
90183
+ reject(Object.assign(
90184
+ new Error(`okx-a2a ${args.join(" ")} failed with ${signal ? `signal=${signal}` : `code=${code2}`}`),
90185
+ { exitCode: code2, signal }
90186
+ ));
90187
+ });
90188
+ });
90189
+ }
90190
+
89895
90191
  // src/listener.ts
89896
90192
  var OFFLINE_REPLAY_SYNC_INTERVAL = 5;
89897
90193
  function shouldRunOfflineReplay(syncCount, interval = OFFLINE_REPLAY_SYNC_INTERVAL) {
@@ -89908,9 +90204,9 @@ function stopClients(service) {
89908
90204
  for (const [address, client] of service.getClients()) {
89909
90205
  try {
89910
90206
  client.stop();
89911
- console.log(`[okx-agent-task] stopped XMTP client ${address}`);
90207
+ logWithTimestamp(`[okx-agent-task] stopped XMTP client ${address}`);
89912
90208
  } catch (err2) {
89913
- console.log(`[okx-agent-task] failed to stop XMTP client ${address}:`, err2);
90209
+ logWithTimestamp(`[okx-agent-task] failed to stop XMTP client ${address}:`, err2);
89914
90210
  }
89915
90211
  }
89916
90212
  }
@@ -89918,12 +90214,12 @@ async function runListener(options = {}) {
89918
90214
  const paths = resolveTaskPaths(options.homeDir);
89919
90215
  const daemonLock = await acquireDaemonLock(paths, process.argv[1] ?? "okx-a2a");
89920
90216
  if (!daemonLock) {
89921
- console.log(
90217
+ logWithTimestamp(
89922
90218
  `[okx-agent-task] another daemon is already running for home=${paths.homeDir}; exiting before starting listeners`
89923
90219
  );
89924
90220
  return;
89925
90221
  }
89926
- console.log(
90222
+ logWithTimestamp(
89927
90223
  `[okx-agent-task] daemon lock acquired pid=${daemonLock.metadata.pid} lock=${paths.daemonLockPath}`
89928
90224
  );
89929
90225
  try {
@@ -89947,17 +90243,17 @@ async function runListenerWithLock(options, paths) {
89947
90243
  stage: "user_attention_ipc_wake",
89948
90244
  reason: "server_error"
89949
90245
  });
89950
- console.log("[okx-agent-task] user_attention IPC wake error:", err2);
90246
+ logWithTimestamp("[okx-agent-task] user_attention IPC wake error:", err2);
89951
90247
  }
89952
90248
  });
89953
- console.log(`[okx-agent-task] user_attention IPC wake listening at ${userAttentionEvents.path}`);
90249
+ logWithTimestamp(`[okx-agent-task] user_attention IPC wake listening at ${userAttentionEvents.path}`);
89954
90250
  } catch (err2) {
89955
90251
  logger.error(LogEvent.IPC_FAILED, err2 instanceof Error ? err2 : new Error(String(err2)), {
89956
90252
  component: "node_listener",
89957
90253
  stage: "user_attention_ipc_start",
89958
90254
  reason: "start_failed"
89959
90255
  });
89960
- console.log("[okx-agent-task] failed to start user_attention IPC wake; watchers will use polling fallback:", err2);
90256
+ logWithTimestamp("[okx-agent-task] failed to start user_attention IPC wake; watchers will use polling fallback:", err2);
89961
90257
  }
89962
90258
  const watcherCoordinator = startUserAttentionWatcherCoordinator({
89963
90259
  store: sessionStore,
@@ -89967,16 +90263,18 @@ async function runListenerWithLock(options, paths) {
89967
90263
  stage: "user_attention_watcher",
89968
90264
  reason: "watcher_error"
89969
90265
  });
89970
- console.log("[okx-agent-task] user_attention watcher coordinator error:", err2);
90266
+ logWithTimestamp("[okx-agent-task] user_attention watcher coordinator error:", err2);
89971
90267
  }
89972
90268
  });
89973
- console.log("[okx-agent-task] user_attention watcher coordinator scanning SQLite watcher state");
90269
+ logWithTimestamp("[okx-agent-task] user_attention watcher coordinator scanning SQLite watcher state");
89974
90270
  const service = XmtpService.getInstance();
89975
90271
  service.setDataDir(paths.xmtpDir);
89976
90272
  service.setTools({
89977
90273
  listAllAgentsWithMetadata: async (previousFingerprint) => listAllAgentsWithMetadata(previousFingerprint),
89978
90274
  fetchSensitiveWords: async () => fetchSensitiveWords(),
89979
- fetchSystemConfig: async () => fetchSystemConfig(),
90275
+ fetchSystemConfig: async () => fetchSystemConfig({
90276
+ notifySessionExpired: (command) => service.tools.notifySessionExpired?.(command)
90277
+ }),
89980
90278
  notifyAgentsWakeup: async (agentIds) => notifyAgentsWakeup(agentIds),
89981
90279
  createSigner: (agent) => createOnchainosSigner(agent),
89982
90280
  createInboundMiddleware: (deps) => createMiddlewareFromCoreDeps(store, deps, {
@@ -90007,13 +90305,23 @@ async function runListenerWithLock(options, paths) {
90007
90305
  }));
90008
90306
  }
90009
90307
  });
90010
- service.setPluginVersion("0.0.13-beta-d0ec14bc63-260622192924");
90308
+ service.setCliVersion("0.0.13");
90011
90309
  await service.init();
90012
- const pluginVersionStatus = service.pluginVersionStatus;
90013
- if (pluginVersionStatus.unavailable) {
90014
- throw new Error(
90015
- `@okxweb3/a2a-node v${"0.0.13-beta-d0ec14bc63-260622192924"} is below the required minimum v${pluginVersionStatus.minVersion}`
90310
+ const startupVersionCheck = await ensureCommunicationMinVersions({
90311
+ systemConfig: service.getSystemConfig(),
90312
+ sessionStore,
90313
+ stage: "startup"
90314
+ });
90315
+ if (startupVersionCheck.updated) {
90316
+ logWithTimestamp(
90317
+ `[okx-agent-task] forced update executed during startup target=${startupVersionCheck.target}; exiting current listener so restarted daemon can take over`
90016
90318
  );
90319
+ await watcherCoordinator.stop();
90320
+ await userAttentionEvents?.close();
90321
+ stopClients(service);
90322
+ sessionStore.close();
90323
+ commands.close();
90324
+ return;
90017
90325
  }
90018
90326
  const systemConfig = service.getSystemConfig();
90019
90327
  if (systemConfig.sentryDsn) {
@@ -90023,17 +90331,17 @@ async function runListenerWithLock(options, paths) {
90023
90331
  agentPlatform: "node"
90024
90332
  });
90025
90333
  } else {
90026
- console.error(
90334
+ errorWithTimestamp(
90027
90335
  "[okx-agent-task] system-config did not return sentryDsn; Sentry not initialized"
90028
90336
  );
90029
90337
  logger.error(LogEvent.SENTRY_INIT_SKIPPED, void 0, {
90030
90338
  onchainosAgentId: "*",
90031
90339
  reason: "system-config missing sentryDsn",
90032
90340
  pluginId: "@okxweb3/a2a-node",
90033
- pluginVersion: "0.0.13-beta-d0ec14bc63-260622192924"
90341
+ pluginVersion: "0.0.13"
90034
90342
  });
90035
90343
  }
90036
- console.log(
90344
+ logWithTimestamp(
90037
90345
  `[okx-agent-task] listener initialized, clients=${service.getClients().size}, home=${store.homeDir}`
90038
90346
  );
90039
90347
  let syncInFlight = false;
@@ -90050,7 +90358,7 @@ async function runListenerWithLock(options, paths) {
90050
90358
  const shouldReplay = shouldRunOfflineReplay(offlineReplaySyncCount);
90051
90359
  offlineReplaySyncCount = nextOfflineReplaySyncCount(offlineReplaySyncCount);
90052
90360
  if (!shouldHeartbeat) {
90053
- console.log("[okx-agent-task] no active agents, skipping heartbeat");
90361
+ logWithTimestamp("[okx-agent-task] no active agents, skipping heartbeat");
90054
90362
  }
90055
90363
  const skippedTiming = { durationMs: 0 };
90056
90364
  const [heartbeatResult, replayResult] = await Promise.all([
@@ -90068,7 +90376,7 @@ async function runListenerWithLock(options, paths) {
90068
90376
  chainIndex: ONCHAINOS_CHAIN_INDEX,
90069
90377
  communicationClass: "onchainos_or_network"
90070
90378
  });
90071
- console.log(`[okx-agent-task] heartbeat failed duration=${heartbeatMs}ms:`, heartbeatResult.error);
90379
+ logWithTimestamp(`[okx-agent-task] heartbeat failed duration=${heartbeatMs}ms:`, heartbeatResult.error);
90072
90380
  }
90073
90381
  if (shouldReplay && replayResult.error) {
90074
90382
  logger.error(LogEvent.OFFLINE_REPLAY_FAILED, replayResult.error instanceof Error ? replayResult.error : new Error(String(replayResult.error)), {
@@ -90078,10 +90386,10 @@ async function runListenerWithLock(options, paths) {
90078
90386
  durationMs: String(replayMs),
90079
90387
  communicationClass: "xmtp_replay_or_storage"
90080
90388
  });
90081
- console.log(`[okx-agent-task] offline replay failed duration=${replayMs}ms:`, replayResult.error);
90389
+ logWithTimestamp(`[okx-agent-task] offline replay failed duration=${replayMs}ms:`, replayResult.error);
90082
90390
  }
90083
90391
  const replaySummary = shouldReplay ? replayResult.value : void 0;
90084
- console.log(
90392
+ logWithTimestamp(
90085
90393
  `[okx-agent-task] sync tick agents=${refresh.agentCount} changed=${refresh.changed ? "yes" : "no"} added=${refresh.added.length} removed=${refresh.removed.length} replayed=${replaySummary?.replayed ?? 0}`
90086
90394
  );
90087
90395
  } catch (err2) {
@@ -90091,7 +90399,7 @@ async function runListenerWithLock(options, paths) {
90091
90399
  durationMs: String(Date.now() - tickStartedAt),
90092
90400
  reason: "sync_tick_exception"
90093
90401
  });
90094
- console.log(`[okx-agent-task] sync tick failed total=${Date.now() - tickStartedAt}ms:`, err2);
90402
+ logWithTimestamp(`[okx-agent-task] sync tick failed total=${Date.now() - tickStartedAt}ms:`, err2);
90095
90403
  } finally {
90096
90404
  syncInFlight = false;
90097
90405
  }
@@ -90107,7 +90415,7 @@ async function runListenerWithLock(options, paths) {
90107
90415
  clearInterval(timer);
90108
90416
  }
90109
90417
  intervalSec = Math.max(10, nextIntervalSec);
90110
- console.log(`[okx-agent-task] scheduled sync interval ${intervalSec}s`);
90418
+ logWithTimestamp(`[okx-agent-task] scheduled sync interval ${intervalSec}s`);
90111
90419
  timer = setInterval(() => {
90112
90420
  void syncTick();
90113
90421
  }, intervalSec * 1e3);
@@ -90122,9 +90430,21 @@ async function runListenerWithLock(options, paths) {
90122
90430
  if (stopping) {
90123
90431
  return;
90124
90432
  }
90433
+ const versionCheck = await ensureCommunicationMinVersions({
90434
+ systemConfig: service.getSystemConfig(),
90435
+ sessionStore,
90436
+ stage: "system_config_refresh"
90437
+ });
90438
+ if (versionCheck.updated) {
90439
+ logWithTimestamp(
90440
+ `[okx-agent-task] forced update executed after system-config refresh target=${versionCheck.target}; stopping current listener`
90441
+ );
90442
+ process.kill(process.pid, "SIGTERM");
90443
+ return;
90444
+ }
90125
90445
  const nextIntervalSec = Math.max(10, service.getSystemConfig().heartbeatInterval);
90126
90446
  if (nextIntervalSec !== previousIntervalSec) {
90127
- console.log(
90447
+ logWithTimestamp(
90128
90448
  `[okx-agent-task] heartbeat interval changed from ${previousIntervalSec}s to ${nextIntervalSec}s; rescheduling sync timer`
90129
90449
  );
90130
90450
  scheduleSyncTimer(nextIntervalSec);
@@ -90135,7 +90455,7 @@ async function runListenerWithLock(options, paths) {
90135
90455
  stage: "system_config_refresh",
90136
90456
  reason: "refresh_failed"
90137
90457
  });
90138
- console.log("[okx-agent-task] system-config refresh failed:", err2);
90458
+ logWithTimestamp("[okx-agent-task] system-config refresh failed:", err2);
90139
90459
  }
90140
90460
  };
90141
90461
  scheduleSyncTimer(intervalSec);
@@ -90155,9 +90475,9 @@ async function runListenerWithLock(options, paths) {
90155
90475
  return;
90156
90476
  }
90157
90477
  stopping = true;
90158
- console.log(`[okx-agent-task] received ${signal}, stopping listener`);
90478
+ logWithTimestamp(`[okx-agent-task] received ${signal}, stopping listener`);
90159
90479
  const forceResolve = setTimeout(() => {
90160
- console.log("[okx-agent-task] listener shutdown timed out; forcing process exit");
90480
+ logWithTimestamp("[okx-agent-task] listener shutdown timed out; forcing process exit");
90161
90481
  resolve4();
90162
90482
  }, SHUTDOWN_FORCE_RESOLVE_MS);
90163
90483
  void (async () => {
@@ -90175,7 +90495,7 @@ async function runListenerWithLock(options, paths) {
90175
90495
  stage: "user_attention_ipc_close",
90176
90496
  reason: "close_failed"
90177
90497
  });
90178
- console.log("[okx-agent-task] failed to close user_attention IPC wake:", err2);
90498
+ logWithTimestamp("[okx-agent-task] failed to close user_attention IPC wake:", err2);
90179
90499
  }
90180
90500
  stopClients(service);
90181
90501
  sessionStore.close();
@@ -90196,117 +90516,6 @@ async function timeSettled(fn) {
90196
90516
  return { durationMs: Date.now() - startedAt, error };
90197
90517
  }
90198
90518
  }
90199
-
90200
- // src/update-cli.ts
90201
- var import_promises6 = require("node:fs/promises");
90202
- var import_node_os6 = require("node:os");
90203
- var import_node_path18 = require("node:path");
90204
- function isPrereleaseVersion(version2) {
90205
- return /\d+\.\d+\.\d+-[0-9A-Za-z.-]+/.test(version2);
90206
- }
90207
- async function normalizeHermesOkxA2aPluginConfig(configFile = resolveHermesConfigPath()) {
90208
- let content3;
90209
- try {
90210
- content3 = await (0, import_promises6.readFile)(configFile, "utf8");
90211
- } catch (error) {
90212
- if (isNodeError(error) && error.code === "ENOENT") {
90213
- return false;
90214
- }
90215
- throw error;
90216
- }
90217
- const trailingNewline = content3.endsWith("\n");
90218
- const lines = content3.replace(/\n$/, "").split(/\n/);
90219
- let changed = false;
90220
- let inPlugins = false;
90221
- let pluginsIndent = -1;
90222
- let inEnabled = false;
90223
- let enabledIndent = -1;
90224
- let emittedOkxA2a = false;
90225
- const output = [];
90226
- for (const line of lines) {
90227
- const currentIndent = lineIndent(line);
90228
- const significant = line.trim() !== "" && !line.trimStart().startsWith("#");
90229
- const parsedListValue = parseYamlListValue(line);
90230
- if (inEnabled && significant && (currentIndent < enabledIndent || currentIndent === enabledIndent && !parsedListValue)) {
90231
- inEnabled = false;
90232
- emittedOkxA2a = false;
90233
- }
90234
- if (inPlugins && significant && currentIndent <= pluginsIndent && !isPluginsHeader(line)) {
90235
- inPlugins = false;
90236
- inEnabled = false;
90237
- emittedOkxA2a = false;
90238
- }
90239
- if (isPluginsHeader(line)) {
90240
- inPlugins = true;
90241
- pluginsIndent = currentIndent;
90242
- output.push(line);
90243
- continue;
90244
- }
90245
- if (inPlugins && isEnabledHeader(line) && currentIndent > pluginsIndent) {
90246
- inEnabled = true;
90247
- enabledIndent = currentIndent;
90248
- emittedOkxA2a = false;
90249
- output.push(line);
90250
- continue;
90251
- }
90252
- if (inEnabled) {
90253
- const parsed = parsedListValue;
90254
- if (parsed && (parsed.value === "okx-a2a" || parsed.value === "platforms/okx-a2a")) {
90255
- if (!emittedOkxA2a) {
90256
- const normalized = `${parsed.indent}- okx-a2a`;
90257
- output.push(normalized);
90258
- changed ||= normalized !== line;
90259
- emittedOkxA2a = true;
90260
- } else {
90261
- changed = true;
90262
- }
90263
- continue;
90264
- }
90265
- }
90266
- output.push(line);
90267
- }
90268
- if (!changed) {
90269
- return false;
90270
- }
90271
- await (0, import_promises6.writeFile)(configFile, `${output.join("\n")}${trailingNewline ? "\n" : ""}`);
90272
- console.log(`[update] normalized Hermes plugins.enabled okx-a2a entry in ${configFile}`);
90273
- return true;
90274
- }
90275
- function resolveHermesConfigPath() {
90276
- return (0, import_node_path18.join)(process.env.HERMES_HOME ?? (0, import_node_path18.join)((0, import_node_os6.homedir)(), ".hermes"), "config.yaml");
90277
- }
90278
- function lineIndent(line) {
90279
- const match = line.match(/^\s*/);
90280
- return match?.[0].length ?? 0;
90281
- }
90282
- function isPluginsHeader(line) {
90283
- return /^[\s]*plugins:[\s]*(?:#.*)?$/.test(line);
90284
- }
90285
- function isEnabledHeader(line) {
90286
- return /^[\s]*enabled:[\s]*(?:#.*)?$/.test(line);
90287
- }
90288
- function parseYamlListValue(line) {
90289
- const match = line.match(/^(\s*)-\s*(?:"([^"]*)"|'([^']*)'|([^#\s]+))(?:\s*(?:#.*)?)?$/);
90290
- if (!match) {
90291
- return null;
90292
- }
90293
- return {
90294
- indent: match[1] ?? "",
90295
- value: match[2] ?? match[3] ?? match[4] ?? ""
90296
- };
90297
- }
90298
- function isNodeError(error) {
90299
- return error instanceof Error && "code" in error;
90300
- }
90301
- function parsePluginYamlVersion(content3) {
90302
- for (const line of content3.split(/\r?\n/)) {
90303
- const match = line.match(/^\s*version:\s*(?:"([^"]+)"|'([^']+)'|([^#\s]+))/);
90304
- if (match) {
90305
- return match[1] ?? match[2] ?? match[3] ?? null;
90306
- }
90307
- }
90308
- return null;
90309
- }
90310
90519
  // Annotate the CommonJS export names for ESM import in node:
90311
90520
  0 && (module.exports = {
90312
90521
  AI_PROVIDERS,
@@ -90318,7 +90527,6 @@ function parsePluginYamlVersion(content3) {
90318
90527
  GatewayOutboundBehavior,
90319
90528
  InvalidXmtpMessageStore,
90320
90529
  OFFLINE_REPLAY_SYNC_INTERVAL,
90321
- OPENCLAW_GATEWAY_ROUTE_GROUP_ID,
90322
90530
  SYSTEM_NOTIFICATION_SESSION_KEY,
90323
90531
  SessionStore,
90324
90532
  SqliteOutboundBehavior,
@@ -90332,7 +90540,6 @@ function parsePluginYamlVersion(content3) {
90332
90540
  bindJobProviderToCurrentDefaultIfMissing,
90333
90541
  bindJobProviderToCurrentRuntimeIfMissing,
90334
90542
  bindMessageJobProviderToCurrentDefault,
90335
- bindOpenClawGatewayRouteFromEnv,
90336
90543
  buildAgentMessageNotice,
90337
90544
  buildAiAdapterCommand,
90338
90545
  buildAiProviderEnv,
@@ -90353,11 +90560,11 @@ function parsePluginYamlVersion(content3) {
90353
90560
  createFileMessageHandler,
90354
90561
  createOutboundBehavior,
90355
90562
  createUserAttentionWatchParentMonitor,
90356
- currentOpenClawGatewaySessionKey,
90357
90563
  detectAiProviders,
90358
90564
  detectCurrentAiProvider,
90359
90565
  detectGatewayInvocation,
90360
90566
  detectRuntime,
90567
+ ensureCommunicationMinVersions,
90361
90568
  ensureDefaultAiProvider,
90362
90569
  extractAiSessionId,
90363
90570
  extractXmtpSentAtMs,
@@ -90365,6 +90572,7 @@ function parsePluginYamlVersion(content3) {
90365
90572
  handleXmtpSendCommand,
90366
90573
  hasAiRuntimeMarker,
90367
90574
  heartbeatUserAttentionWatcher,
90575
+ isBelowRequiredVersion,
90368
90576
  isOriginalParentProcessAlive,
90369
90577
  isPrereleaseVersion,
90370
90578
  isRetryableOpenClawGatewayError,
@@ -90387,8 +90595,6 @@ function parsePluginYamlVersion(content3) {
90387
90595
  resolveConfiguredAiProviderForJob,
90388
90596
  resolveDirectCommunicationSessionTarget,
90389
90597
  resolveOpenClawGatewayConfig,
90390
- resolveOpenClawGatewayRoute,
90391
- resolveOpenClawGatewayRoutes,
90392
90598
  resolveSystemNotificationTargets,
90393
90599
  resolveTaskConfigPath,
90394
90600
  resolveTaskHome,