@okxweb3/a2a-node 0.0.15 → 0.0.16-beta-d0ec14bc63-260623110312

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 +700 -167
  2. package/dist/index.js +511 -19
  3. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -1959,6 +1959,7 @@ var init_command_store = __esm({
1959
1959
  myAgentId: params.myAgentId,
1960
1960
  toAgentId: params.toAgentId,
1961
1961
  toXmtpAddress: params.toXmtpAddress,
1962
+ gatewaySessionKeys: params.gatewaySessionKeys,
1962
1963
  createdAt: Date.now()
1963
1964
  };
1964
1965
  }
@@ -7369,7 +7370,7 @@ function buildConnectParams(config, instanceId, protocolVersion) {
7369
7370
  client: {
7370
7371
  id: "gateway-client",
7371
7372
  displayName: "okx-a2a-node",
7372
- version: "0.0.15",
7373
+ version: "0.0.16-beta-d0ec14bc63-260623110312",
7373
7374
  platform: "node",
7374
7375
  mode: "backend",
7375
7376
  instanceId
@@ -7380,7 +7381,7 @@ function buildConnectParams(config, instanceId, protocolVersion) {
7380
7381
  commands: [],
7381
7382
  permissions: {},
7382
7383
  locale: Intl.DateTimeFormat().resolvedOptions().locale || "en-US",
7383
- userAgent: `okx-a2a-node/${"0.0.15"}`,
7384
+ userAgent: `okx-a2a-node/${"0.0.16-beta-d0ec14bc63-260623110312"}`,
7384
7385
  auth: {
7385
7386
  ...config.token ? { token: config.token } : {},
7386
7387
  ...config.password ? { password: config.password } : {}
@@ -7714,6 +7715,324 @@ var init_openclaw_session_key = __esm({
7714
7715
  }
7715
7716
  });
7716
7717
 
7718
+ // src/openclaw-route.ts
7719
+ function currentOpenClawGatewaySessionKey(env = process.env) {
7720
+ for (const candidate of currentOpenClawGatewaySessionCandidates(env)) {
7721
+ if (candidate.ok) {
7722
+ return candidate.sessionKey;
7723
+ }
7724
+ }
7725
+ return null;
7726
+ }
7727
+ function bindOpenClawGatewayRouteFromEnv(store, input, env = process.env) {
7728
+ const jobId = normalizeText(input.jobId);
7729
+ if (!jobId) {
7730
+ return null;
7731
+ }
7732
+ const existingBinding = store.getJobProviderBinding(jobId);
7733
+ if (existingBinding && existingBinding.provider !== "openclaw") {
7734
+ return null;
7735
+ }
7736
+ let routes = readOpenClawRouteEntries(store, jobId);
7737
+ let firstBound = null;
7738
+ for (const candidate of currentOpenClawGatewaySessionCandidates(env, input.gatewaySessionKeys)) {
7739
+ if (!candidate.ok) {
7740
+ logOpenClawRouteSkip(candidate.reason, {
7741
+ jobId,
7742
+ sessionKey: candidate.sessionKey,
7743
+ existingRoute: resolveOpenClawGatewayRoute(store, { jobId })
7744
+ });
7745
+ continue;
7746
+ }
7747
+ const channel = channelFromOpenClawGatewaySessionKey(candidate.sessionKey);
7748
+ if (!channel) {
7749
+ logOpenClawRouteSkip("invalid_gateway_session_key", {
7750
+ jobId,
7751
+ sessionKey: candidate.sessionKey,
7752
+ existingRoute: resolveOpenClawGatewayRoute(store, { jobId })
7753
+ });
7754
+ continue;
7755
+ }
7756
+ const existingRoute = routes.find((route2) => route2.platform === channel) ?? null;
7757
+ if (existingRoute) {
7758
+ firstBound ??= existingRoute.gatewaySessionKey || existingRoute.sessionKey || null;
7759
+ continue;
7760
+ }
7761
+ const route = buildOpenClawRouteEntry(candidate.sessionKey, channel);
7762
+ routes = [...routes, route];
7763
+ const binding = store.upsertJobGatewayRoute({ jobId, provider: "openclaw", route });
7764
+ if (binding.provider !== "openclaw") {
7765
+ return null;
7766
+ }
7767
+ firstBound ??= route.gatewaySessionKey || route.sessionKey || null;
7768
+ }
7769
+ if (firstBound) {
7770
+ return firstBound;
7771
+ }
7772
+ return resolveOpenClawGatewayRoute(store, { jobId })?.sessionKey ?? null;
7773
+ }
7774
+ function currentOpenClawGatewaySessionCandidates(env = process.env, explicitSessionKeys) {
7775
+ const platform = normalizeText(env.OKX_A2A_CURRENT_GATEWAY_PLATFORM);
7776
+ const chatId = normalizeText(env.OKX_A2A_CURRENT_GATEWAY_CHAT_ID);
7777
+ const threadId = normalizeText(env.OKX_A2A_CURRENT_GATEWAY_THREAD_ID);
7778
+ const rawKeys = [
7779
+ ...Array.isArray(explicitSessionKeys) ? explicitSessionKeys : [],
7780
+ ...readGatewaySessionKeysEnv(env),
7781
+ normalizeText(env.OKX_A2A_CURRENT_GATEWAY_SESSION_KEY),
7782
+ platform && chatId ? deriveOpenClawGatewaySessionKey({ platform, chatId, threadId }) : null,
7783
+ normalizeText(env.OKX_A2A_CURRENT_SESSION_KEY),
7784
+ ...readSingleActiveOriginSessionKey(env)
7785
+ ];
7786
+ const seen = /* @__PURE__ */ new Set();
7787
+ const candidates = [];
7788
+ for (const key of rawKeys) {
7789
+ const normalized = normalizeText(key);
7790
+ if (!normalized || seen.has(normalized)) {
7791
+ continue;
7792
+ }
7793
+ seen.add(normalized);
7794
+ candidates.push(validateOpenClawGatewaySessionKey(normalized));
7795
+ }
7796
+ if (candidates.length > 0) {
7797
+ return candidates;
7798
+ }
7799
+ return [{ ok: false, reason: "missing_gateway_session_key" }];
7800
+ }
7801
+ function resolveOpenClawGatewayRoute(store, input) {
7802
+ return resolveOpenClawGatewayRoutes(store, input)[0] ?? null;
7803
+ }
7804
+ function resolveOpenClawGatewayRoutes(store, input) {
7805
+ const jobId = normalizeText(input.jobId) ?? inferJobIdFromSessionKey(normalizeText(input.sessionKey));
7806
+ if (jobId) {
7807
+ return readOpenClawRouteEntries(store, jobId).map((route) => toOpenClawGatewayRoute(route, jobId));
7808
+ }
7809
+ return [];
7810
+ }
7811
+ function isValidOpenClawGatewaySessionKey(sessionKey) {
7812
+ return validateOpenClawGatewaySessionKey(sessionKey).ok;
7813
+ }
7814
+ function buildOpenClawRouteEntry(sessionKey, channel) {
7815
+ const parsed = parseOpenClawGatewaySessionKey(sessionKey);
7816
+ return {
7817
+ platform: channel,
7818
+ chatId: parsed.chatId ?? sessionKey,
7819
+ chatType: parsed.threadId ? "thread" : "dm",
7820
+ sessionKey,
7821
+ gatewaySessionKey: sessionKey,
7822
+ chatName: "",
7823
+ ...parsed.threadId ? { threadId: parsed.threadId } : { threadId: "" },
7824
+ userId: "",
7825
+ userName: "",
7826
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
7827
+ };
7828
+ }
7829
+ function toOpenClawGatewayRoute(route, jobId) {
7830
+ const sessionKey = route.gatewaySessionKey || route.sessionKey || "";
7831
+ return {
7832
+ sessionKey,
7833
+ jobId,
7834
+ routeSessionKey: route.sessionKey || sessionKey,
7835
+ updatedAt: route.updatedAt ?? "",
7836
+ channel: route.platform
7837
+ };
7838
+ }
7839
+ function readOpenClawRouteEntries(store, jobId) {
7840
+ const binding = store?.getJobProviderBinding(jobId);
7841
+ if (binding?.provider !== "openclaw") {
7842
+ return [];
7843
+ }
7844
+ const routes = binding.gatewayRoutes ?? [];
7845
+ const seenChannels = /* @__PURE__ */ new Set();
7846
+ const validRoutes = [];
7847
+ for (const route of routes) {
7848
+ const sessionKey = normalizeText(route.gatewaySessionKey) ?? normalizeText(route.sessionKey);
7849
+ const channel = channelFromOpenClawGatewaySessionKey(sessionKey);
7850
+ if (!sessionKey || !channel || seenChannels.has(channel)) {
7851
+ continue;
7852
+ }
7853
+ seenChannels.add(channel);
7854
+ validRoutes.push({
7855
+ platform: channel,
7856
+ chatId: route.chatId,
7857
+ chatName: route.chatName ?? "",
7858
+ chatType: route.chatType || (route.threadId ? "thread" : "dm"),
7859
+ sessionKey: route.sessionKey,
7860
+ gatewaySessionKey: sessionKey,
7861
+ threadId: route.threadId ?? "",
7862
+ userId: route.userId ?? "",
7863
+ userName: route.userName ?? "",
7864
+ ...route.updatedAt ? { updatedAt: route.updatedAt } : {}
7865
+ });
7866
+ }
7867
+ return validRoutes;
7868
+ }
7869
+ function parseOpenClawGatewaySessionKey(sessionKey) {
7870
+ const parts = sessionKey.split(":");
7871
+ if (parts.length < 4 || parts[0] !== "agent") {
7872
+ return {};
7873
+ }
7874
+ const platform = parts[2];
7875
+ const targetKind = parts[3];
7876
+ if (platform === "discord" && targetKind === "thread") {
7877
+ return {
7878
+ ...parts[4] ? { chatId: parts[4] } : {},
7879
+ ...parts[5] ? { threadId: parts[5] } : {}
7880
+ };
7881
+ }
7882
+ if (platform === "discord" && targetKind === "channel") {
7883
+ return parts[4] ? { chatId: parts[4] } : {};
7884
+ }
7885
+ if (platform === "discord" && targetKind === "dm") {
7886
+ return parts[4] ? { chatId: parts[4] } : {};
7887
+ }
7888
+ if (platform === "telegram" && targetKind === "direct") {
7889
+ return parts[4] ? { chatId: parts[4] } : {};
7890
+ }
7891
+ if (platform === "telegram" && targetKind === "group") {
7892
+ return {
7893
+ ...parts[4] ? { chatId: parts[4] } : {},
7894
+ ...parts[6] ? { threadId: parts[6] } : {}
7895
+ };
7896
+ }
7897
+ return {};
7898
+ }
7899
+ function validateOpenClawGatewaySessionKey(sessionKey) {
7900
+ const key = normalizeText(sessionKey);
7901
+ if (!key) {
7902
+ return { ok: false, reason: "missing_gateway_session_key" };
7903
+ }
7904
+ if (key.startsWith("backup:")) {
7905
+ return { ok: false, reason: "internal_gateway_session_key", sessionKey: key };
7906
+ }
7907
+ if (key === "agent:main") {
7908
+ return { ok: true, sessionKey: key };
7909
+ }
7910
+ const parts = key.split(":");
7911
+ if (parts.length < 4 || parts[0] !== "agent" || !parts[1]) {
7912
+ return { ok: false, reason: "invalid_gateway_session_key", sessionKey: key };
7913
+ }
7914
+ const platform = parts[2];
7915
+ if (!platform || platform === "okx-a2a" || NON_DELIVERY_CHANNELS.has(platform)) {
7916
+ return { ok: false, reason: "internal_gateway_session_key", sessionKey: key };
7917
+ }
7918
+ return { ok: true, sessionKey: key };
7919
+ }
7920
+ function channelFromOpenClawGatewaySessionKey(sessionKey) {
7921
+ const key = normalizeText(sessionKey);
7922
+ if (!key) {
7923
+ return null;
7924
+ }
7925
+ if (key === "agent:main") {
7926
+ return "main";
7927
+ }
7928
+ const validation = validateOpenClawGatewaySessionKey(key);
7929
+ if (!validation.ok) {
7930
+ return null;
7931
+ }
7932
+ return key.split(":")[2] ?? null;
7933
+ }
7934
+ function deriveOpenClawGatewaySessionKey(input) {
7935
+ const chatId = encodeURIComponent(input.chatId);
7936
+ const threadId = input.threadId ? encodeURIComponent(input.threadId) : "";
7937
+ if (input.platform === "telegram") {
7938
+ return threadId ? `agent:main:telegram:group:${chatId}:topic:${threadId}` : `agent:main:telegram:direct:${chatId}`;
7939
+ }
7940
+ return threadId ? `agent:main:${input.platform}:thread:${chatId}:${threadId}` : `agent:main:${input.platform}:dm:${chatId}`;
7941
+ }
7942
+ function readGatewaySessionKeysEnv(env) {
7943
+ const raw = normalizeText(env[CURRENT_GATEWAY_SESSION_KEYS_ENV]);
7944
+ if (!raw) {
7945
+ return [];
7946
+ }
7947
+ try {
7948
+ const parsed = JSON.parse(raw);
7949
+ if (Array.isArray(parsed)) {
7950
+ return parsed.filter((item) => typeof item === "string" && item.trim().length > 0);
7951
+ }
7952
+ } catch {
7953
+ }
7954
+ return raw.split(",").map((item) => item.trim()).filter(Boolean);
7955
+ }
7956
+ function readSingleActiveOriginSessionKey(env) {
7957
+ const path = (0, import_node_path11.join)(resolveTaskHome2(env), "run", "gateway-route-origins.json");
7958
+ if (!(0, import_node_fs8.existsSync)(path)) {
7959
+ return [];
7960
+ }
7961
+ try {
7962
+ const parsed = JSON.parse((0, import_node_fs8.readFileSync)(path, "utf8"));
7963
+ if (!isRecord(parsed) || !Array.isArray(parsed.origins)) {
7964
+ return [];
7965
+ }
7966
+ const now = Date.now();
7967
+ const valid = parsed.origins.filter((item) => isRecord(item)).map((item) => ({
7968
+ sessionKey: normalizeText(typeof item.sessionKey === "string" ? item.sessionKey : null),
7969
+ count: typeof item.count === "number" && Number.isFinite(item.count) ? item.count : 0,
7970
+ updatedAt: typeof item.updatedAt === "number" && Number.isFinite(item.updatedAt) ? item.updatedAt : 0
7971
+ })).filter((item) => item.sessionKey && item.count > 0 && now - item.updatedAt <= ACTIVE_ORIGIN_TTL_MS && validateOpenClawGatewaySessionKey(item.sessionKey).ok);
7972
+ const sessionKeys = [...new Set(valid.map((item) => item.sessionKey).filter(Boolean))];
7973
+ return sessionKeys.length === 1 ? sessionKeys : [];
7974
+ } catch (err2) {
7975
+ console.error(
7976
+ `[openclaw-route] failed to read active gateway route origin state: ${err2 instanceof Error ? err2.message : String(err2)}`
7977
+ );
7978
+ return [];
7979
+ }
7980
+ }
7981
+ function resolveTaskHome2(env) {
7982
+ return env.OKX_AGENT_TASK_HOME?.trim() || (0, import_node_path11.join)((0, import_node_os3.homedir)(), ".okx-agent-task");
7983
+ }
7984
+ function logOpenClawRouteSkip(reason, input) {
7985
+ if (reason === "missing_gateway_session_key") {
7986
+ return;
7987
+ }
7988
+ console.error(
7989
+ `[openclaw-route] skipped gateway route bind reason=${reason} jobId=${input.jobId} sessionKey=${input.sessionKey ?? "(none)"} existingRoute=${input.existingRoute?.sessionKey ?? "(none)"}`
7990
+ );
7991
+ }
7992
+ function inferJobIdFromSessionKey(sessionKey) {
7993
+ if (!sessionKey) {
7994
+ return null;
7995
+ }
7996
+ const parts = sessionKey.split(":");
7997
+ if (parts.length >= 2 && parts[0] === "job") {
7998
+ return safeDecode2(parts[1]);
7999
+ }
8000
+ if (sessionKey.startsWith("backup:")) {
8001
+ return safeDecode2(sessionKey.slice("backup:".length));
8002
+ }
8003
+ const gatewayJob = /(?:^|[?&:])job=([^:&]+)/.exec(sessionKey);
8004
+ if (gatewayJob?.[1]) {
8005
+ return safeDecode2(gatewayJob[1]);
8006
+ }
8007
+ return null;
8008
+ }
8009
+ function normalizeText(value) {
8010
+ const text = value?.trim();
8011
+ return text ? text : null;
8012
+ }
8013
+ function isRecord(value) {
8014
+ return typeof value === "object" && value !== null && !Array.isArray(value);
8015
+ }
8016
+ function safeDecode2(value) {
8017
+ try {
8018
+ return decodeURIComponent(value);
8019
+ } catch {
8020
+ return value;
8021
+ }
8022
+ }
8023
+ var import_node_fs8, import_node_os3, import_node_path11, CURRENT_GATEWAY_SESSION_KEYS_ENV, NON_DELIVERY_CHANNELS, ACTIVE_ORIGIN_TTL_MS;
8024
+ var init_openclaw_route = __esm({
8025
+ "src/openclaw-route.ts"() {
8026
+ "use strict";
8027
+ import_node_fs8 = require("node:fs");
8028
+ import_node_os3 = require("node:os");
8029
+ import_node_path11 = require("node:path");
8030
+ CURRENT_GATEWAY_SESSION_KEYS_ENV = "OKX_A2A_CURRENT_GATEWAY_SESSION_KEYS";
8031
+ NON_DELIVERY_CHANNELS = /* @__PURE__ */ new Set(["heartbeat", "cron", "webhook", "voice"]);
8032
+ ACTIVE_ORIGIN_TTL_MS = 30 * 6e4;
8033
+ }
8034
+ });
8035
+
7717
8036
  // ../../node_modules/@sentry/utils/cjs/is.js
7718
8037
  var require_is = __commonJS({
7719
8038
  "../../node_modules/@sentry/utils/cjs/is.js"(exports2) {
@@ -9594,7 +9913,7 @@ var require_path = __commonJS({
9594
9913
  function isAbsolute2(path) {
9595
9914
  return path.charAt(0) === "/";
9596
9915
  }
9597
- function join20(...args) {
9916
+ function join21(...args) {
9598
9917
  return normalizePath(args.join("/"));
9599
9918
  }
9600
9919
  function dirname6(path) {
@@ -9619,7 +9938,7 @@ var require_path = __commonJS({
9619
9938
  exports2.basename = basename5;
9620
9939
  exports2.dirname = dirname6;
9621
9940
  exports2.isAbsolute = isAbsolute2;
9622
- exports2.join = join20;
9941
+ exports2.join = join21;
9623
9942
  exports2.normalizePath = normalizePath;
9624
9943
  exports2.relative = relative;
9625
9944
  exports2.resolve = resolve7;
@@ -23494,7 +23813,7 @@ function assertLatestUserFanoutDelivered(operation, payload) {
23494
23813
  const result = payload;
23495
23814
  const dispatched = Array.isArray(result.dispatched) ? result.dispatched.length : null;
23496
23815
  const failed = Array.isArray(result.failed) ? result.failed.length : null;
23497
- if (result.ok === false || dispatched === 0) {
23816
+ if (dispatched === 0 || result.ok === false && dispatched === null) {
23498
23817
  throw Object.assign(
23499
23818
  new Error(
23500
23819
  `${operation} did not deliver to any OpenClaw user session (dispatched=${dispatched ?? "unknown"} failed=${failed ?? "unknown"})`
@@ -23520,6 +23839,7 @@ var init_outbound_behavior = __esm({
23520
23839
  init_user_attention_ipc();
23521
23840
  init_openclaw_gateway();
23522
23841
  init_openclaw_session_key();
23842
+ init_openclaw_route();
23523
23843
  init_sentry_logger();
23524
23844
  SqliteOutboundBehavior = class {
23525
23845
  provider;
@@ -23649,6 +23969,7 @@ var init_outbound_behavior = __esm({
23649
23969
  }
23650
23970
  async dispatchSessionMessage(input) {
23651
23971
  const gatewaySessionKey = this.resolveGatewaySessionKey(input);
23972
+ this.bindUserRouteForJob(input.jobId);
23652
23973
  errorWithTimestamp(
23653
23974
  `${GATEWAY_OUTBOUND_LOG_PREFIX} dispatchSessionMessage sessionKey=${input.sessionKey} gatewaySessionKey=${gatewaySessionKey} jobId=${input.jobId ?? "(none)"} agentId=${input.agentId ?? "(none)"} messageId=${input.messageId ?? "(none)"}`
23654
23975
  );
@@ -23706,6 +24027,12 @@ var init_outbound_behavior = __esm({
23706
24027
  }));
23707
24028
  }
23708
24029
  }
24030
+ bindUserRouteForJob(jobId) {
24031
+ if (!this.store || !jobId) {
24032
+ return;
24033
+ }
24034
+ bindOpenClawGatewayRouteFromEnv(this.store, { jobId });
24035
+ }
23709
24036
  resolveGatewaySessionKey(input) {
23710
24037
  const stored = this.sessionMetaStore?.getSession(input.sessionKey);
23711
24038
  return toOpenClawGatewaySessionKey({
@@ -23717,11 +24044,20 @@ var init_outbound_behavior = __esm({
23717
24044
  });
23718
24045
  }
23719
24046
  async dispatchUser(input) {
24047
+ const routed = this.resolveUserGatewaySessionKey(input);
24048
+ if (routed) {
24049
+ await this.dispatchUserToGatewaySession(input, routed);
24050
+ return null;
24051
+ }
23720
24052
  errorWithTimestamp(
23721
24053
  `${GATEWAY_OUTBOUND_LOG_PREFIX} dispatchUser latestUserSessions jobId=${input.jobId ?? "(none)"} idempotencyKey=${input.idempotencyKey ?? "(none)"}`
23722
24054
  );
23723
24055
  try {
23724
- const result = await this.gateway.callDispatchUserToLatestSessions({ content: input.userContent });
24056
+ const result = await this.gateway.callDispatchUserToLatestSessions({
24057
+ content: input.userContent,
24058
+ ...input.jobId ? { jobId: input.jobId } : {},
24059
+ ...input.sessionKey ? { currentSessionKey: input.sessionKey } : {}
24060
+ });
23725
24061
  assertLatestUserFanoutDelivered("okx-a2a.dispatch_user", result);
23726
24062
  errorWithTimestamp(`${GATEWAY_OUTBOUND_LOG_PREFIX} dispatchUser latestUserSessions ok`);
23727
24063
  logger.info(LogEvent.USER_DISPATCHED, gatewayOutboundExtra("okx-a2a.dispatch_user", {
@@ -23759,14 +24095,90 @@ var init_outbound_behavior = __esm({
23759
24095
  }
23760
24096
  return null;
23761
24097
  }
24098
+ resolveUserGatewaySessionKey(input) {
24099
+ const routes = resolveOpenClawGatewayRoutes(this.sessionMetaStore, input);
24100
+ if (routes.length > 0) {
24101
+ return { sessionKeys: routes.map((route) => route.sessionKey), source: "stored_openclaw_routes" };
24102
+ }
24103
+ if (input.sessionKey?.startsWith("agent:")) {
24104
+ return isValidOpenClawGatewaySessionKey(input.sessionKey) ? { sessionKeys: [input.sessionKey], source: "explicit_gateway_session" } : null;
24105
+ }
24106
+ return null;
24107
+ }
24108
+ async dispatchUserToGatewaySession(input, routed) {
24109
+ const gatewaySessionKey = routed.sessionKeys.join(",");
24110
+ console.error(
24111
+ `${GATEWAY_OUTBOUND_LOG_PREFIX} dispatchUser routed sessionKey=${input.sessionKey ?? "(none)"} gatewaySessionKey=${gatewaySessionKey} source=${routed.source} jobId=${input.jobId ?? "(none)"} idempotencyKey=${input.idempotencyKey ?? "(none)"}`
24112
+ );
24113
+ try {
24114
+ const result = await this.gateway.callDispatchUserToLatestSessions({
24115
+ content: input.userContent,
24116
+ label: "okx-a2a",
24117
+ ...routed.source === "stored_openclaw_routes" ? { sessionKeys: routed.sessionKeys } : { sessionKey: routed.sessionKeys[0] }
24118
+ });
24119
+ assertLatestUserFanoutDelivered("okx-a2a.dispatch_user", result);
24120
+ console.error(`${GATEWAY_OUTBOUND_LOG_PREFIX} dispatchUser routed ok gatewaySessionKey=${gatewaySessionKey} source=${routed.source}`);
24121
+ logger.info(LogEvent.USER_DISPATCHED, gatewayOutboundExtra("okx-a2a.dispatch_user", {
24122
+ sessionKey: input.sessionKey ?? "",
24123
+ gatewaySessionKey,
24124
+ jobId: input.jobId ?? "",
24125
+ source: routed.source,
24126
+ status: "delivered"
24127
+ }));
24128
+ } catch (err2) {
24129
+ if (!this.store || !isRetryableOpenClawGatewayError(err2)) {
24130
+ logger.error(LogEvent.USER_DISPATCH_FAILED, err2 instanceof Error ? err2 : new Error(String(err2)), gatewayOutboundExtra("okx-a2a.dispatch_user", {
24131
+ sessionKey: input.sessionKey ?? "",
24132
+ gatewaySessionKey,
24133
+ jobId: input.jobId ?? "",
24134
+ source: routed.source,
24135
+ status: "failed"
24136
+ }));
24137
+ throw err2;
24138
+ }
24139
+ this.store.enqueuePendingGatewayDelivery({
24140
+ kind: "chat_inject",
24141
+ provider: this.provider,
24142
+ sessionKey: routed.sessionKeys[0] ?? "openclaw:routed-user-sessions",
24143
+ content: input.userContent,
24144
+ jobId: input.jobId ?? null,
24145
+ messageId: input.idempotencyKey ?? null
24146
+ });
24147
+ console.error(
24148
+ `${GATEWAY_OUTBOUND_LOG_PREFIX} dispatchUser routed buffered gatewaySessionKey=${gatewaySessionKey} source=${routed.source} idempotencyKey=${input.idempotencyKey ?? "(none)"}: ${err2 instanceof Error ? err2.message : String(err2)}`
24149
+ );
24150
+ logger.error(LogEvent.USER_DISPATCH_FAILED, err2 instanceof Error ? err2 : new Error(String(err2)), gatewayOutboundExtra("okx-a2a.dispatch_user", {
24151
+ sessionKey: input.sessionKey ?? "",
24152
+ gatewaySessionKey,
24153
+ jobId: input.jobId ?? "",
24154
+ source: routed.source,
24155
+ status: "buffered"
24156
+ }));
24157
+ logger.info(LogEvent.GATEWAY_DELIVERY_BUFFERED, gatewayOutboundExtra("okx-a2a.dispatch_user", {
24158
+ sessionKey: input.sessionKey ?? "",
24159
+ gatewaySessionKey,
24160
+ jobId: input.jobId ?? "",
24161
+ messageId: input.idempotencyKey ?? "",
24162
+ source: routed.source,
24163
+ status: "buffered"
24164
+ }));
24165
+ }
24166
+ }
23762
24167
  async promptUser(input) {
24168
+ const routed = this.resolveUserGatewaySessionKey(input);
24169
+ if (routed) {
24170
+ await this.promptUserToGatewaySession(input, routed);
24171
+ return null;
24172
+ }
23763
24173
  errorWithTimestamp(
23764
24174
  `${GATEWAY_OUTBOUND_LOG_PREFIX} promptUser latestUserSessions jobId=${input.jobId ?? "(none)"} idempotencyKey=${input.idempotencyKey ?? "(none)"}`
23765
24175
  );
23766
24176
  try {
23767
24177
  const result = await this.gateway.callPromptUserToLatestSessions({
23768
24178
  userContent: input.userContent,
23769
- llmContent: input.llmContent
24179
+ llmContent: input.llmContent,
24180
+ ...input.jobId ? { jobId: input.jobId } : {},
24181
+ ...input.sessionKey ? { currentSessionKey: input.sessionKey } : {}
23770
24182
  });
23771
24183
  assertLatestUserFanoutDelivered("okx-a2a.prompt_user", result);
23772
24184
  errorWithTimestamp(`${GATEWAY_OUTBOUND_LOG_PREFIX} promptUser latestUserSessions ok`);
@@ -23806,6 +24218,66 @@ var init_outbound_behavior = __esm({
23806
24218
  }
23807
24219
  return null;
23808
24220
  }
24221
+ async promptUserToGatewaySession(input, routed) {
24222
+ const gatewaySessionKey = routed.sessionKeys.join(",");
24223
+ console.error(
24224
+ `${GATEWAY_OUTBOUND_LOG_PREFIX} promptUser routed sessionKey=${input.sessionKey ?? "(none)"} gatewaySessionKey=${gatewaySessionKey} source=${routed.source} jobId=${input.jobId ?? "(none)"} idempotencyKey=${input.idempotencyKey ?? "(none)"}`
24225
+ );
24226
+ try {
24227
+ const result = await this.gateway.callPromptUserToLatestSessions({
24228
+ userContent: input.userContent,
24229
+ llmContent: input.llmContent,
24230
+ ...routed.source === "stored_openclaw_routes" ? { sessionKeys: routed.sessionKeys } : { sessionKey: routed.sessionKeys[0] }
24231
+ });
24232
+ assertLatestUserFanoutDelivered("okx-a2a.prompt_user", result);
24233
+ console.error(`${GATEWAY_OUTBOUND_LOG_PREFIX} promptUser routed ok gatewaySessionKey=${gatewaySessionKey} source=${routed.source}`);
24234
+ logger.info(LogEvent.PROMPT_USER_CHECKPOINT, gatewayOutboundExtra("routed_prompt_user", {
24235
+ sessionKey: input.sessionKey ?? "",
24236
+ gatewaySessionKey,
24237
+ jobId: input.jobId ?? "",
24238
+ source: routed.source,
24239
+ status: "delivered"
24240
+ }));
24241
+ } catch (err2) {
24242
+ if (!this.store || !isRetryableOpenClawGatewayError(err2)) {
24243
+ logger.error(LogEvent.PROMPT_USER_FAILED, err2 instanceof Error ? err2 : new Error(String(err2)), gatewayOutboundExtra("routed_prompt_user", {
24244
+ sessionKey: input.sessionKey ?? "",
24245
+ gatewaySessionKey,
24246
+ jobId: input.jobId ?? "",
24247
+ source: routed.source,
24248
+ status: "failed"
24249
+ }));
24250
+ throw err2;
24251
+ }
24252
+ this.store.enqueuePendingGatewayDelivery({
24253
+ kind: "chat_inject",
24254
+ provider: this.provider,
24255
+ sessionKey: routed.sessionKeys[0] ?? "openclaw:routed-user-sessions",
24256
+ content: input.userContent,
24257
+ llmContent: input.llmContent,
24258
+ jobId: input.jobId ?? null,
24259
+ messageId: input.idempotencyKey ?? null
24260
+ });
24261
+ console.error(
24262
+ `${GATEWAY_OUTBOUND_LOG_PREFIX} promptUser routed buffered gatewaySessionKey=${gatewaySessionKey} source=${routed.source} idempotencyKey=${input.idempotencyKey ?? "(none)"}: ${err2 instanceof Error ? err2.message : String(err2)}`
24263
+ );
24264
+ logger.error(LogEvent.PROMPT_USER_FAILED, err2 instanceof Error ? err2 : new Error(String(err2)), gatewayOutboundExtra("routed_prompt_user", {
24265
+ sessionKey: input.sessionKey ?? "",
24266
+ gatewaySessionKey,
24267
+ jobId: input.jobId ?? "",
24268
+ source: routed.source,
24269
+ status: "buffered"
24270
+ }));
24271
+ logger.info(LogEvent.GATEWAY_DELIVERY_BUFFERED, gatewayOutboundExtra("routed_prompt_user", {
24272
+ sessionKey: input.sessionKey ?? "",
24273
+ gatewaySessionKey,
24274
+ jobId: input.jobId ?? "",
24275
+ messageId: input.idempotencyKey ?? "",
24276
+ source: routed.source,
24277
+ status: "buffered"
24278
+ }));
24279
+ }
24280
+ }
23809
24281
  };
23810
24282
  }
23811
24283
  });
@@ -23823,23 +24295,23 @@ function resolveAiPermissionPreset(options = {}) {
23823
24295
  }
23824
24296
  function readAiPermissionPresetFromConfig(homeDir) {
23825
24297
  const configPath = resolveTaskConfigPath(homeDir);
23826
- if (!(0, import_node_fs8.existsSync)(configPath)) {
24298
+ if (!(0, import_node_fs9.existsSync)(configPath)) {
23827
24299
  return null;
23828
24300
  }
23829
- const raw = readSimpleTomlStringValue((0, import_node_fs8.readFileSync)(configPath, "utf8"), "ai.permissions", "preset");
24301
+ const raw = readSimpleTomlStringValue((0, import_node_fs9.readFileSync)(configPath, "utf8"), "ai.permissions", "preset");
23830
24302
  return raw ? normalizeAiPermissionPreset(raw, configPath) : null;
23831
24303
  }
23832
24304
  function writeAiPermissionPresetToConfig(homeDir, preset) {
23833
24305
  const normalized = normalizeAiPermissionPreset(preset, "permission preset");
23834
24306
  ensureTaskDir(homeDir);
23835
24307
  const configPath = resolveTaskConfigPath(homeDir);
23836
- const current = (0, import_node_fs8.existsSync)(configPath) ? (0, import_node_fs8.readFileSync)(configPath, "utf8") : "";
24308
+ const current = (0, import_node_fs9.existsSync)(configPath) ? (0, import_node_fs9.readFileSync)(configPath, "utf8") : "";
23837
24309
  const next = upsertSimpleTomlStringValue(current, "ai.permissions", "preset", normalized);
23838
- (0, import_node_fs8.writeFileSync)(configPath, next, "utf8");
24310
+ (0, import_node_fs9.writeFileSync)(configPath, next, "utf8");
23839
24311
  return normalized;
23840
24312
  }
23841
24313
  function resolveTaskConfigPath(homeDir) {
23842
- return (0, import_node_path11.join)(homeDir, "config.toml");
24314
+ return (0, import_node_path12.join)(homeDir, "config.toml");
23843
24315
  }
23844
24316
  function normalizeAiPermissionPreset(value, source) {
23845
24317
  const normalized = value.trim().toLowerCase();
@@ -23912,12 +24384,12 @@ function upsertSimpleTomlStringValue(text, section, key, value) {
23912
24384
  function escapeRegExp(value) {
23913
24385
  return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
23914
24386
  }
23915
- var import_node_fs8, import_node_path11, AI_PERMISSION_PRESETS, DEFAULT_AI_PERMISSION_PRESET;
24387
+ var import_node_fs9, import_node_path12, AI_PERMISSION_PRESETS, DEFAULT_AI_PERMISSION_PRESET;
23916
24388
  var init_task_config = __esm({
23917
24389
  "src/task-config.ts"() {
23918
24390
  "use strict";
23919
- import_node_fs8 = require("node:fs");
23920
- import_node_path11 = require("node:path");
24391
+ import_node_fs9 = require("node:fs");
24392
+ import_node_path12 = require("node:path");
23921
24393
  init_paths();
23922
24394
  AI_PERMISSION_PRESETS = ["bypass", "auto"];
23923
24395
  DEFAULT_AI_PERMISSION_PRESET = "bypass";
@@ -23932,7 +24404,7 @@ var init_sentry_config = __esm({
23932
24404
  environment = process.env.SENTRY_ENV === "dev" ? "dev" : "prod";
23933
24405
  SENTRY_CONFIG = {
23934
24406
  projectName: "okx/openclaw-okx-a2a-extension",
23935
- release: "0.0.15",
24407
+ release: "0.0.16-beta-d0ec14bc63-260623110312",
23936
24408
  environment
23937
24409
  };
23938
24410
  }
@@ -23981,7 +24453,7 @@ function extractExecutablePath(stdout) {
23981
24453
  }
23982
24454
  function isExecutable2(path) {
23983
24455
  try {
23984
- (0, import_node_fs9.accessSync)(path, import_node_fs9.constants.X_OK);
24456
+ (0, import_node_fs10.accessSync)(path, import_node_fs10.constants.X_OK);
23985
24457
  return true;
23986
24458
  } catch {
23987
24459
  return false;
@@ -24050,12 +24522,12 @@ async function exec(args) {
24050
24522
  throw err2;
24051
24523
  }
24052
24524
  }
24053
- var import_node_fs9, import_node_child_process3, import_node_util, execFileAsync, resolvedBin, REDACTED_VALUE_FLAGS;
24525
+ var import_node_fs10, import_node_child_process3, import_node_util, execFileAsync, resolvedBin, REDACTED_VALUE_FLAGS;
24054
24526
  var init_bin = __esm({
24055
24527
  "../core/src/xmtp-sdk/onchainos/bin.ts"() {
24056
24528
  "use strict";
24057
24529
  init_log();
24058
- import_node_fs9 = require("node:fs");
24530
+ import_node_fs10 = require("node:fs");
24059
24531
  import_node_child_process3 = require("node:child_process");
24060
24532
  import_node_util = require("node:util");
24061
24533
  init_sentry_logger();
@@ -66763,7 +67235,7 @@ function createAsyncStreamProxy(stream) {
66763
67235
  function isHexString(value) {
66764
67236
  return typeof value === "string" && /^0x(?:[0-9a-fA-F]{2})+$/.test(value);
66765
67237
  }
66766
- var import_node_bindings, import_node_bindings2, import_types, import_node_path12, import_node_process, ApiUrls, HistorySyncUrls, DecodedMessage, CodecNotFoundError, InboxReassignError, AccountAlreadyAssociatedError, InvalidGroupMembershipChangeError, MissingContentTypeError, SignerUnavailableError, ClientNotInitializedError, StreamFailedError, StreamInvalidRetryAttemptsError, AsyncStream, usableProperties, isUsableProperty, wait, DEFAULT_RETRY_DELAY, DEFAULT_RETRY_ATTEMPTS, createStream, Conversation, Dm, Group, Conversations, DebugInformation, Preferences, generateInboxId, getInboxIdForIdentifier, createClient, Client;
67238
+ var import_node_bindings, import_node_bindings2, import_types, import_node_path13, import_node_process, ApiUrls, HistorySyncUrls, DecodedMessage, CodecNotFoundError, InboxReassignError, AccountAlreadyAssociatedError, InvalidGroupMembershipChangeError, MissingContentTypeError, SignerUnavailableError, ClientNotInitializedError, StreamFailedError, StreamInvalidRetryAttemptsError, AsyncStream, usableProperties, isUsableProperty, wait, DEFAULT_RETRY_DELAY, DEFAULT_RETRY_ATTEMPTS, createStream, Conversation, Dm, Group, Conversations, DebugInformation, Preferences, generateInboxId, getInboxIdForIdentifier, createClient, Client;
66767
67239
  var init_dist4 = __esm({
66768
67240
  "../../node_modules/@xmtp/node-sdk/dist/index.js"() {
66769
67241
  init_dist2();
@@ -66772,7 +67244,7 @@ var init_dist4 = __esm({
66772
67244
  import_node_bindings2 = require("@xmtp/node-bindings");
66773
67245
  init_dist();
66774
67246
  import_types = require("node:util/types");
66775
- import_node_path12 = require("node:path");
67247
+ import_node_path13 = require("node:path");
66776
67248
  import_node_process = __toESM(require("node:process"), 1);
66777
67249
  ApiUrls = {
66778
67250
  local: "http://localhost:5556",
@@ -68018,7 +68490,7 @@ var init_dist4 = __esm({
68018
68490
  const inboxId = await getInboxIdForIdentifier(identifier, env, gatewayHost) || generateInboxId(identifier, options?.nonce);
68019
68491
  let dbPath;
68020
68492
  if (options?.dbPath === void 0) {
68021
- dbPath = (0, import_node_path12.join)(import_node_process.default.cwd(), `xmtp-${env}-${inboxId}.db3`);
68493
+ dbPath = (0, import_node_path13.join)(import_node_process.default.cwd(), `xmtp-${env}-${inboxId}.db3`);
68022
68494
  } else if (typeof options.dbPath === "function") {
68023
68495
  dbPath = options.dbPath(inboxId);
68024
68496
  } else {
@@ -82804,7 +83276,7 @@ var init_agent_status = __esm({
82804
83276
 
82805
83277
  // ../core/src/xmtp-sdk/index.ts
82806
83278
  function cachePath(dataDir, fileName) {
82807
- return (0, import_node_path13.join)(dataDir, fileName);
83279
+ return (0, import_node_path14.join)(dataDir, fileName);
82808
83280
  }
82809
83281
  function ensureCacheDir(dataDir) {
82810
83282
  ensureA2aTaskDir(dataDir);
@@ -82827,10 +83299,10 @@ function isSessionExpiredError(err2) {
82827
83299
  function loadSensitiveWordsFromCache(dataDir) {
82828
83300
  try {
82829
83301
  const path = cachePath(dataDir, "sensitive-words.json");
82830
- if (!(0, import_node_fs10.existsSync)(path)) {
83302
+ if (!(0, import_node_fs11.existsSync)(path)) {
82831
83303
  return null;
82832
83304
  }
82833
- const data = JSON.parse((0, import_node_fs10.readFileSync)(path, "utf-8"));
83305
+ const data = JSON.parse((0, import_node_fs11.readFileSync)(path, "utf-8"));
82834
83306
  if (Array.isArray(data)) {
82835
83307
  return data;
82836
83308
  }
@@ -82844,7 +83316,7 @@ function loadSensitiveWordsFromCache(dataDir) {
82844
83316
  function saveSensitiveWordsToCache(dataDir, words) {
82845
83317
  try {
82846
83318
  ensureCacheDir(dataDir);
82847
- (0, import_node_fs10.writeFileSync)(cachePath(dataDir, "sensitive-words.json"), JSON.stringify(words));
83319
+ (0, import_node_fs11.writeFileSync)(cachePath(dataDir, "sensitive-words.json"), JSON.stringify(words));
82848
83320
  } catch (err2) {
82849
83321
  logWithTimestamp(`[xmtp-sdk] failed to write sensitive-words.json:`, err2);
82850
83322
  logger.error(LogEvent.CACHE_WRITE_FAILED, err2 instanceof Error ? err2 : new Error(String(err2)), { cacheName: "sensitive-words" });
@@ -82886,10 +83358,10 @@ async function loadSensitiveWordsWith(dataDir, fetcher) {
82886
83358
  function loadSystemConfigFromCache(dataDir) {
82887
83359
  try {
82888
83360
  const path = cachePath(dataDir, "system-config.json");
82889
- if (!(0, import_node_fs10.existsSync)(path)) {
83361
+ if (!(0, import_node_fs11.existsSync)(path)) {
82890
83362
  return null;
82891
83363
  }
82892
- const data = JSON.parse((0, import_node_fs10.readFileSync)(path, "utf-8"));
83364
+ const data = JSON.parse((0, import_node_fs11.readFileSync)(path, "utf-8"));
82893
83365
  if (data && typeof data === "object" && !Array.isArray(data)) {
82894
83366
  return data;
82895
83367
  }
@@ -82903,7 +83375,7 @@ function loadSystemConfigFromCache(dataDir) {
82903
83375
  function saveSystemConfigToCache(dataDir, config) {
82904
83376
  try {
82905
83377
  ensureCacheDir(dataDir);
82906
- (0, import_node_fs10.writeFileSync)(cachePath(dataDir, "system-config.json"), JSON.stringify(config));
83378
+ (0, import_node_fs11.writeFileSync)(cachePath(dataDir, "system-config.json"), JSON.stringify(config));
82907
83379
  } catch (err2) {
82908
83380
  logWithTimestamp(`[xmtp-sdk] failed to write system-config.json:`, err2);
82909
83381
  logger.error(LogEvent.CACHE_WRITE_FAILED, err2 instanceof Error ? err2 : new Error(String(err2)), { cacheName: "system-config" });
@@ -82950,10 +83422,10 @@ function loadSyncByAddress(dataDir) {
82950
83422
  const map = /* @__PURE__ */ new Map();
82951
83423
  try {
82952
83424
  const path = cachePath(dataDir, "last-sync.json");
82953
- if (!(0, import_node_fs10.existsSync)(path)) {
83425
+ if (!(0, import_node_fs11.existsSync)(path)) {
82954
83426
  return map;
82955
83427
  }
82956
- const data = JSON.parse((0, import_node_fs10.readFileSync)(path, "utf-8"));
83428
+ const data = JSON.parse((0, import_node_fs11.readFileSync)(path, "utf-8"));
82957
83429
  const obj = data?.syncByAddress;
82958
83430
  if (obj && typeof obj === "object" && !Array.isArray(obj)) {
82959
83431
  for (const [addr, ts] of Object.entries(obj)) {
@@ -82972,9 +83444,9 @@ function saveSyncForAddress(dataDir, address, timestampMs) {
82972
83444
  try {
82973
83445
  let data = {};
82974
83446
  const path = cachePath(dataDir, "last-sync.json");
82975
- if ((0, import_node_fs10.existsSync)(path)) {
83447
+ if ((0, import_node_fs11.existsSync)(path)) {
82976
83448
  try {
82977
- const raw = JSON.parse((0, import_node_fs10.readFileSync)(path, "utf-8"));
83449
+ const raw = JSON.parse((0, import_node_fs11.readFileSync)(path, "utf-8"));
82978
83450
  if (raw && typeof raw === "object" && !Array.isArray(raw)) {
82979
83451
  data = raw;
82980
83452
  }
@@ -82985,7 +83457,7 @@ function saveSyncForAddress(dataDir, address, timestampMs) {
82985
83457
  data.syncByAddress = {};
82986
83458
  }
82987
83459
  data.syncByAddress[address] = timestampMs;
82988
- (0, import_node_fs10.writeFileSync)(path, JSON.stringify(data, null, 2));
83460
+ (0, import_node_fs11.writeFileSync)(path, JSON.stringify(data, null, 2));
82989
83461
  } catch (err2) {
82990
83462
  logWithTimestamp(
82991
83463
  `[xmtp-sdk] failed to write last-sync.json (address=${address}):`,
@@ -83162,13 +83634,13 @@ function createOfflineReplayAddressSummary(address) {
83162
83634
  durationMs: 0
83163
83635
  };
83164
83636
  }
83165
- var import_node_fs10, import_node_path13, DEFAULT_DATA_DIR, SENSITIVE_WORDS_LAZY_RETRY_COOLDOWN_MS, SESSION_EXPIRED_RE, SYSTEM_CONFIG_DEFAULTS, SEMVER_RE, SENDER_BLACKLISTED_MESSAGE, RECIPIENT_BLACKLISTED_MESSAGE, XmtpService;
83637
+ var import_node_fs11, import_node_path14, DEFAULT_DATA_DIR, SENSITIVE_WORDS_LAZY_RETRY_COOLDOWN_MS, SESSION_EXPIRED_RE, SYSTEM_CONFIG_DEFAULTS, SEMVER_RE, SENDER_BLACKLISTED_MESSAGE, RECIPIENT_BLACKLISTED_MESSAGE, XmtpService;
83166
83638
  var init_xmtp_sdk = __esm({
83167
83639
  "../core/src/xmtp-sdk/index.ts"() {
83168
83640
  "use strict";
83169
83641
  init_log();
83170
- import_node_fs10 = require("node:fs");
83171
- import_node_path13 = require("node:path");
83642
+ import_node_fs11 = require("node:fs");
83643
+ import_node_path14 = require("node:path");
83172
83644
  init_dist4();
83173
83645
  init_sentry_logger();
83174
83646
  init_extract_job_id();
@@ -85182,12 +85654,12 @@ function loadSqlite3() {
85182
85654
  process.emitWarning = originalEmitWarning;
85183
85655
  }
85184
85656
  }
85185
- var import_node_fs11, import_node_path14, DatabaseSync3, InvalidXmtpMessageStore;
85657
+ var import_node_fs12, import_node_path15, DatabaseSync3, InvalidXmtpMessageStore;
85186
85658
  var init_invalid_message_store = __esm({
85187
85659
  "src/invalid-message-store.ts"() {
85188
85660
  "use strict";
85189
- import_node_fs11 = require("node:fs");
85190
- import_node_path14 = require("node:path");
85661
+ import_node_fs12 = require("node:fs");
85662
+ import_node_path15 = require("node:path");
85191
85663
  init_paths();
85192
85664
  ({ DatabaseSync: DatabaseSync3 } = loadSqlite3());
85193
85665
  InvalidXmtpMessageStore = class {
@@ -85195,8 +85667,8 @@ var init_invalid_message_store = __esm({
85195
85667
  db;
85196
85668
  constructor(homeDir) {
85197
85669
  const paths = resolveTaskPaths(homeDir);
85198
- this.dbPath = (0, import_node_path14.join)(paths.sqliteDir, "invalid-xmtp-messages.sqlite");
85199
- (0, import_node_fs11.mkdirSync)((0, import_node_path14.dirname)(this.dbPath), { recursive: true });
85670
+ this.dbPath = (0, import_node_path15.join)(paths.sqliteDir, "invalid-xmtp-messages.sqlite");
85671
+ (0, import_node_fs12.mkdirSync)((0, import_node_path15.dirname)(this.dbPath), { recursive: true });
85200
85672
  this.db = new DatabaseSync3(this.dbPath);
85201
85673
  this.ensureReady();
85202
85674
  }
@@ -85431,15 +85903,27 @@ function resolveOutboundProvider(store, input) {
85431
85903
  if (input.override) {
85432
85904
  return input.override;
85433
85905
  }
85906
+ if (input.jobId && resolveOpenClawGatewayRoute(store, { jobId: input.jobId })) {
85907
+ return "openclaw";
85908
+ }
85434
85909
  try {
85435
- return resolveConfiguredAiProviderForJob({
85910
+ const configured = resolveConfiguredAiProviderForJob({
85436
85911
  store,
85437
85912
  jobId: input.jobId,
85438
85913
  env: process.env
85439
- }) ?? "codex";
85914
+ });
85915
+ if (configured) {
85916
+ return configured;
85917
+ }
85440
85918
  } catch {
85441
- return "codex";
85442
85919
  }
85920
+ if (readSyncedOpenClawGatewayConfig(store.homeDir)) {
85921
+ if (input.jobId?.trim()) {
85922
+ return store.bindJobProviderIfMissing({ jobId: input.jobId.trim(), provider: "openclaw" }).binding.provider;
85923
+ }
85924
+ return "openclaw";
85925
+ }
85926
+ return "codex";
85443
85927
  }
85444
85928
  async function notifyAgentMessageToUserAttention(input) {
85445
85929
  const ownedStore = input.store ? null : new SessionStore();
@@ -85537,6 +86021,8 @@ var init_agent_message_notice = __esm({
85537
86021
  init_session_store();
85538
86022
  init_ai_provider();
85539
86023
  init_outbound_behavior();
86024
+ init_openclaw_route();
86025
+ init_openclaw_gateway_config();
85540
86026
  DIRECTION_PREFIX = {
85541
86027
  ["outbound" /* OUTBOUND */]: "\u{1F4E4} [Sent]",
85542
86028
  ["inbound" /* INBOUND */]: "\u{1F4E5} [Received]"
@@ -85591,6 +86077,9 @@ function bindOutboundJobProviderToCurrentDefault(sessionStore, jobId) {
85591
86077
  logWithTimestamp(`[okx-agent-task] job provider bind failed from outbound-xmtp: job=${jobId}`, err2);
85592
86078
  }
85593
86079
  }
86080
+ function bindOutboundOpenClawRouteIfCurrent(sessionStore, jobId, gatewaySessionKeys) {
86081
+ bindOpenClawGatewayRouteFromEnv(sessionStore, { jobId, gatewaySessionKeys });
86082
+ }
85594
86083
  function buildTaskPayload(replyToMessageId) {
85595
86084
  return {
85596
86085
  taskMinVersion: TASK_MIN_VERSION,
@@ -86025,6 +86514,7 @@ async function handleSqliteGroupSendCommand(params) {
86025
86514
  myAgentXmtpAddress: myXmtpAddress,
86026
86515
  toAgentXmtpAddress: remote.toXmtpAddress
86027
86516
  });
86517
+ bindOutboundOpenClawRouteIfCurrent(sessionStore, command.jobId, command.gatewaySessionKeys);
86028
86518
  return { conversation: conversation2, created: created2 };
86029
86519
  }
86030
86520
  );
@@ -86351,7 +86841,7 @@ async function handleXmtpSendCommand(params) {
86351
86841
  const sessionStore2 = params.sessionStore ?? ownedStore2;
86352
86842
  try {
86353
86843
  bindOutboundJobProviderToCurrentDefault(sessionStore2, command.jobId);
86354
- resolveConfiguredAiProviderForJob({ store: sessionStore2, jobId: command.jobId });
86844
+ bindOutboundOpenClawRouteIfCurrent(sessionStore2, command.jobId, command.gatewaySessionKeys);
86355
86845
  return await handleSqliteGroupSendCommand({
86356
86846
  command,
86357
86847
  service,
@@ -86365,7 +86855,7 @@ async function handleXmtpSendCommand(params) {
86365
86855
  const sessionStore = params.sessionStore ?? ownedStore;
86366
86856
  try {
86367
86857
  bindOutboundJobProviderToCurrentDefault(sessionStore, command.jobId);
86368
- resolveConfiguredAiProviderForJob({ store: sessionStore, jobId: command.jobId });
86858
+ bindOutboundOpenClawRouteIfCurrent(sessionStore, command.jobId, command.gatewaySessionKeys);
86369
86859
  const { file, sessionAgentId } = await readFileForSend({
86370
86860
  command,
86371
86861
  store,
@@ -86457,6 +86947,7 @@ var init_xmtp_send = __esm({
86457
86947
  init_session_store();
86458
86948
  init_ai_provider();
86459
86949
  init_agent_message_notice();
86950
+ init_openclaw_route();
86460
86951
  TASK_MIN_VERSION = 1;
86461
86952
  sqliteGroupSessionPromises = /* @__PURE__ */ new Map();
86462
86953
  resolvedAgentByIdCache = /* @__PURE__ */ new Map();
@@ -86545,7 +87036,7 @@ function buildAiAdapterCommand(options) {
86545
87036
  function readCodexAddDirs(env = process.env) {
86546
87037
  const raw = env.OKX_A2A_AI_CODEX_ADD_DIRS ?? env.OKX_AGENT_TASK_CODEX_ADD_DIRS ?? "";
86547
87038
  const seen = /* @__PURE__ */ new Set();
86548
- return raw.split(import_node_path15.delimiter).map((value) => expandHomePath(value.trim())).filter(Boolean).filter((dir) => {
87039
+ return raw.split(import_node_path16.delimiter).map((value) => expandHomePath(value.trim())).filter(Boolean).filter((dir) => {
86549
87040
  if (seen.has(dir)) {
86550
87041
  return false;
86551
87042
  }
@@ -86555,10 +87046,10 @@ function readCodexAddDirs(env = process.env) {
86555
87046
  }
86556
87047
  function expandHomePath(value) {
86557
87048
  if (value === "~") {
86558
- return (0, import_node_os3.homedir)();
87049
+ return (0, import_node_os4.homedir)();
86559
87050
  }
86560
87051
  if (value.startsWith("~/")) {
86561
- return (0, import_node_path15.join)((0, import_node_os3.homedir)(), value.slice(2));
87052
+ return (0, import_node_path16.join)((0, import_node_os4.homedir)(), value.slice(2));
86562
87053
  }
86563
87054
  return value;
86564
87055
  }
@@ -86764,9 +87255,9 @@ function formatOpenClawSessionKey(sessionKey, agentId) {
86764
87255
  function buildClaudeAddDirArgs(homeDir, env) {
86765
87256
  const dirs = [
86766
87257
  homeDir,
86767
- (0, import_node_path15.join)((0, import_node_os3.homedir)(), ".agents"),
86768
- (0, import_node_path15.join)(__dirname, ".."),
86769
- ...env.OKX_A2A_AI_CLAUDE_ADD_DIRS ? env.OKX_A2A_AI_CLAUDE_ADD_DIRS.split(import_node_path15.delimiter).filter(Boolean) : []
87258
+ (0, import_node_path16.join)((0, import_node_os4.homedir)(), ".agents"),
87259
+ (0, import_node_path16.join)(__dirname, ".."),
87260
+ ...env.OKX_A2A_AI_CLAUDE_ADD_DIRS ? env.OKX_A2A_AI_CLAUDE_ADD_DIRS.split(import_node_path16.delimiter).filter(Boolean) : []
86770
87261
  ];
86771
87262
  return ["--add-dir", ...[...new Set(dirs)]];
86772
87263
  }
@@ -86818,17 +87309,17 @@ function applyArgTemplate(template, options) {
86818
87309
  const homeDir = options.homeDir ?? resolveTaskPaths().homeDir;
86819
87310
  const cwd = options.cwd ?? process.cwd();
86820
87311
  return template.map((arg) => {
86821
- return arg.replaceAll("{prompt}", options.prompt).replaceAll("{sessionId}", options.sessionId ?? "").replaceAll("{homeDir}", homeDir).replaceAll("{cwd}", cwd).replaceAll("{repoCli}", (0, import_node_path15.join)(__dirname, "cli.js"));
87312
+ return arg.replaceAll("{prompt}", options.prompt).replaceAll("{sessionId}", options.sessionId ?? "").replaceAll("{homeDir}", homeDir).replaceAll("{cwd}", cwd).replaceAll("{repoCli}", (0, import_node_path16.join)(__dirname, "cli.js"));
86822
87313
  });
86823
87314
  }
86824
- var import_node_child_process4, import_node_os3, import_node_path15, CLAUDE_ALLOWED_TOOLS, CLAUDE_PERMISSION_MODES, CODEX_SANDBOX_MODES, CODEX_APPROVAL_POLICIES;
87315
+ var import_node_child_process4, import_node_os4, import_node_path16, CLAUDE_ALLOWED_TOOLS, CLAUDE_PERMISSION_MODES, CODEX_SANDBOX_MODES, CODEX_APPROVAL_POLICIES;
86825
87316
  var init_ai_adapter = __esm({
86826
87317
  "src/ai-adapter.ts"() {
86827
87318
  "use strict";
86828
87319
  init_log();
86829
87320
  import_node_child_process4 = require("node:child_process");
86830
- import_node_os3 = require("node:os");
86831
- import_node_path15 = require("node:path");
87321
+ import_node_os4 = require("node:os");
87322
+ import_node_path16 = require("node:path");
86832
87323
  init_ai_command();
86833
87324
  init_paths();
86834
87325
  init_session_store();
@@ -86869,7 +87360,7 @@ function aiRunSentryExtra(input) {
86869
87360
  closeSignal: input.closeSignal ?? "",
86870
87361
  timedOut: input.timedOut === void 0 ? "" : String(input.timedOut),
86871
87362
  aiSessionId: input.aiSessionId ?? "",
86872
- aiLogFile: input.logPath ? (0, import_node_path16.basename)(input.logPath) : "",
87363
+ aiLogFile: input.logPath ? (0, import_node_path17.basename)(input.logPath) : "",
86873
87364
  commandPendingMs: input.commandPendingMs ?? "",
86874
87365
  queueWaitMs: input.queueWaitMs ?? "",
86875
87366
  cliMs: input.cliMs ?? "",
@@ -86901,7 +87392,7 @@ function aiRunToolFailureSentryExtra(failure, context) {
86901
87392
  closeSignal: context.closeSignal ?? "",
86902
87393
  timedOut: String(context.timedOut),
86903
87394
  aiSessionId: context.aiSessionId ?? "",
86904
- aiLogFile: (0, import_node_path16.basename)(context.logPath)
87395
+ aiLogFile: (0, import_node_path17.basename)(context.logPath)
86905
87396
  }).filter(([, value]) => value !== "");
86906
87397
  return entries.reduce((out, [key, value]) => {
86907
87398
  out[key] = String(value);
@@ -86924,7 +87415,7 @@ function safeProcessCwd() {
86924
87415
  }
86925
87416
  function isDirectory(path) {
86926
87417
  try {
86927
- return (0, import_node_fs12.statSync)(path).isDirectory();
87418
+ return (0, import_node_fs13.statSync)(path).isDirectory();
86928
87419
  } catch {
86929
87420
  return false;
86930
87421
  }
@@ -86969,13 +87460,13 @@ function extractProviderErrorMessage(text) {
86969
87460
  } catch {
86970
87461
  continue;
86971
87462
  }
86972
- if (!isRecord(parsed)) {
87463
+ if (!isRecord2(parsed)) {
86973
87464
  continue;
86974
87465
  }
86975
87466
  if (typeof parsed.message === "string" && parsed.message.trim()) {
86976
87467
  return parsed.message.trim();
86977
87468
  }
86978
- if (isRecord(parsed.error) && typeof parsed.error.message === "string" && parsed.error.message.trim()) {
87469
+ if (isRecord2(parsed.error) && typeof parsed.error.message === "string" && parsed.error.message.trim()) {
86979
87470
  return parsed.error.message.trim();
86980
87471
  }
86981
87472
  }
@@ -87013,7 +87504,7 @@ function parseAiToolFailureLine(provider, line, claudeToolCommands) {
87013
87504
  return null;
87014
87505
  }
87015
87506
  function parseCodexToolFailure(event, rawEvent) {
87016
- if (!isRecord(event) || event.type !== "item.completed" || !isRecord(event.item)) {
87507
+ if (!isRecord2(event) || event.type !== "item.completed" || !isRecord2(event.item)) {
87017
87508
  return null;
87018
87509
  }
87019
87510
  const item = event.item;
@@ -87080,7 +87571,7 @@ function extractCodexStructuredToolFailure(text) {
87080
87571
  } catch {
87081
87572
  return null;
87082
87573
  }
87083
- if (!isRecord(parsed) || !isRecord(parsed.toolFailure)) {
87574
+ if (!isRecord2(parsed) || !isRecord2(parsed.toolFailure)) {
87084
87575
  return null;
87085
87576
  }
87086
87577
  return normalizeCodexStructuredToolFailure(parsed.toolFailure, text);
@@ -87124,7 +87615,7 @@ function extractCodexToolFailureMarker(text) {
87124
87615
  } catch {
87125
87616
  return null;
87126
87617
  }
87127
- if (!isRecord(parsed) || parsed.errorType !== "permission_denied") {
87618
+ if (!isRecord2(parsed) || parsed.errorType !== "permission_denied") {
87128
87619
  return null;
87129
87620
  }
87130
87621
  const tool = typeof parsed.tool === "string" && parsed.tool.trim() ? parsed.tool.trim() : "command_execution";
@@ -87213,11 +87704,11 @@ function extractDeniedFilesystemPath(text) {
87213
87704
  }
87214
87705
  function getPreferredCodexWritableRoot(target) {
87215
87706
  const expanded = expandHomePath2(target);
87216
- const home = (0, import_node_os4.homedir)();
87707
+ const home = (0, import_node_os5.homedir)();
87217
87708
  const appRoots = [
87218
- (0, import_node_path16.join)(home, ".onchainos", "task"),
87219
- (0, import_node_path16.join)(home, ".onchainos", "deliverables"),
87220
- (0, import_node_path16.join)(home, ".okx-agent-task")
87709
+ (0, import_node_path17.join)(home, ".onchainos", "task"),
87710
+ (0, import_node_path17.join)(home, ".onchainos", "deliverables"),
87711
+ (0, import_node_path17.join)(home, ".okx-agent-task")
87221
87712
  ];
87222
87713
  for (const root of appRoots) {
87223
87714
  if (expanded === root || expanded.startsWith(`${root}/`)) {
@@ -87232,25 +87723,25 @@ function inferAppOwnedCodexWritableRoot(failure) {
87232
87723
  return void 0;
87233
87724
  }
87234
87725
  if (containsOnchainosCommand(command) && /\b0x[0-9a-fA-F]{16,}\b/.test(command)) {
87235
- return (0, import_node_path16.join)((0, import_node_os4.homedir)(), ".onchainos", "task");
87726
+ return (0, import_node_path17.join)((0, import_node_os5.homedir)(), ".onchainos", "task");
87236
87727
  }
87237
87728
  return void 0;
87238
87729
  }
87239
87730
  function expandHomePath2(value) {
87240
87731
  if (value === "~") {
87241
- return (0, import_node_os4.homedir)();
87732
+ return (0, import_node_os5.homedir)();
87242
87733
  }
87243
87734
  if (value.startsWith("~/")) {
87244
- return (0, import_node_path16.join)((0, import_node_os4.homedir)(), value.slice(2));
87735
+ return (0, import_node_path17.join)((0, import_node_os5.homedir)(), value.slice(2));
87245
87736
  }
87246
87737
  return value;
87247
87738
  }
87248
87739
  function parseClaudeToolFailure(event, rawEvent, claudeToolCommands) {
87249
- if (!isRecord(event)) {
87740
+ if (!isRecord2(event)) {
87250
87741
  return null;
87251
87742
  }
87252
87743
  rememberClaudeToolCommands(event, claudeToolCommands);
87253
- const toolUseResult = isRecord(event.tool_use_result) ? event.tool_use_result : null;
87744
+ const toolUseResult = isRecord2(event.tool_use_result) ? event.tool_use_result : null;
87254
87745
  const toolResult = findClaudeToolResult(event);
87255
87746
  if (!toolUseResult && !toolResult) {
87256
87747
  return null;
@@ -87277,7 +87768,7 @@ function parseClaudeToolFailure(event, rawEvent, claudeToolCommands) {
87277
87768
  });
87278
87769
  }
87279
87770
  function rememberClaudeToolCommands(event, commands) {
87280
- if (!isRecord(event.message)) {
87771
+ if (!isRecord2(event.message)) {
87281
87772
  return;
87282
87773
  }
87283
87774
  const content3 = event.message.content;
@@ -87285,17 +87776,17 @@ function rememberClaudeToolCommands(event, commands) {
87285
87776
  return;
87286
87777
  }
87287
87778
  for (const part of content3) {
87288
- if (!isRecord(part) || part.type !== "tool_use" || typeof part.id !== "string") {
87779
+ if (!isRecord2(part) || part.type !== "tool_use" || typeof part.id !== "string") {
87289
87780
  continue;
87290
87781
  }
87291
- if (part.name !== "Bash" || !isRecord(part.input) || typeof part.input.command !== "string") {
87782
+ if (part.name !== "Bash" || !isRecord2(part.input) || typeof part.input.command !== "string") {
87292
87783
  continue;
87293
87784
  }
87294
87785
  commands.set(part.id, part.input.command);
87295
87786
  }
87296
87787
  }
87297
87788
  function findClaudeToolResult(event) {
87298
- if (!isRecord(event.message)) {
87789
+ if (!isRecord2(event.message)) {
87299
87790
  return null;
87300
87791
  }
87301
87792
  const content3 = event.message.content;
@@ -87303,7 +87794,7 @@ function findClaudeToolResult(event) {
87303
87794
  return null;
87304
87795
  }
87305
87796
  for (const part of content3) {
87306
- if (!isRecord(part) || part.type !== "tool_result") {
87797
+ if (!isRecord2(part) || part.type !== "tool_result") {
87307
87798
  continue;
87308
87799
  }
87309
87800
  return {
@@ -87322,7 +87813,7 @@ function extractExplicitExitCode(text) {
87322
87813
  const value = Number(match[1]);
87323
87814
  return Number.isFinite(value) ? value : null;
87324
87815
  }
87325
- function isRecord(value) {
87816
+ function isRecord2(value) {
87326
87817
  return typeof value === "object" && value !== null;
87327
87818
  }
87328
87819
  function appendOutput(current, chunk, max = 4e3) {
@@ -87493,7 +87984,7 @@ function parseSessionKeyDetails(sessionKey) {
87493
87984
  kind: sessionKey || "unknown"
87494
87985
  };
87495
87986
  }
87496
- function inferJobIdFromSessionKey(sessionKey) {
87987
+ function inferJobIdFromSessionKey2(sessionKey) {
87497
87988
  const jobPrefixMatch = /^job:([^:]+):/.exec(sessionKey);
87498
87989
  if (jobPrefixMatch?.[1]) {
87499
87990
  return normalizeOptionalText(safeDecodeURIComponent(jobPrefixMatch[1]));
@@ -87713,7 +88204,7 @@ function extractCodexAgentMessagePermissionText(output4) {
87713
88204
  } catch {
87714
88205
  continue;
87715
88206
  }
87716
- if (isRecord(parsed) && parsed.type === "item.completed" && isRecord(parsed.item) && parsed.item.type === "agent_message" && typeof parsed.item.text === "string" && classifyAiDispatchError(parsed.item.text) === "permission_denied") {
88207
+ if (isRecord2(parsed) && parsed.type === "item.completed" && isRecord2(parsed.item) && parsed.item.type === "agent_message" && typeof parsed.item.text === "string" && classifyAiDispatchError(parsed.item.text) === "permission_denied") {
87717
88208
  return parsed.item.text;
87718
88209
  }
87719
88210
  }
@@ -88169,17 +88660,17 @@ function shortenJobId2(jobId) {
88169
88660
  }
88170
88661
  return `${jobId.slice(0, 6)}\u2026${jobId.slice(-4)}`;
88171
88662
  }
88172
- var import_node_crypto8, import_node_fs12, import_promises5, import_node_child_process5, import_node_os4, import_node_path16, AiRunner, CODEX_TOOL_FAILURE_MARKER;
88663
+ var import_node_crypto8, import_node_fs13, import_promises5, import_node_child_process5, import_node_os5, import_node_path17, AiRunner, CODEX_TOOL_FAILURE_MARKER;
88173
88664
  var init_ai_runner = __esm({
88174
88665
  "src/ai-runner.ts"() {
88175
88666
  "use strict";
88176
88667
  init_log();
88177
88668
  import_node_crypto8 = require("node:crypto");
88178
- import_node_fs12 = require("node:fs");
88669
+ import_node_fs13 = require("node:fs");
88179
88670
  import_promises5 = require("node:fs/promises");
88180
88671
  import_node_child_process5 = require("node:child_process");
88181
- import_node_os4 = require("node:os");
88182
- import_node_path16 = require("node:path");
88672
+ import_node_os5 = require("node:os");
88673
+ import_node_path17 = require("node:path");
88183
88674
  init_ai_command();
88184
88675
  init_paths();
88185
88676
  init_file_store();
@@ -88279,7 +88770,7 @@ var init_ai_runner = __esm({
88279
88770
  if (sessionJobId) {
88280
88771
  return sessionJobId;
88281
88772
  }
88282
- return inferJobIdFromSessionKey(request.sessionKey);
88773
+ return inferJobIdFromSessionKey2(request.sessionKey);
88283
88774
  }
88284
88775
  buildRunQueueKey(request) {
88285
88776
  if (request.source === "job-dispatch") {
@@ -88306,7 +88797,7 @@ var init_ai_runner = __esm({
88306
88797
  ensureTaskDir(this.logsDir);
88307
88798
  const lifecycleLogsEnabled = isAiLifecycleLoggingEnabled();
88308
88799
  const logPath = lifecycleLogsEnabled ? this.buildRunLogPath(request) : "";
88309
- const log = lifecycleLogsEnabled ? (0, import_node_fs12.createWriteStream)(logPath, { flags: "a" }) : null;
88800
+ const log = lifecycleLogsEnabled ? (0, import_node_fs13.createWriteStream)(logPath, { flags: "a" }) : null;
88310
88801
  let existing = null;
88311
88802
  let storeReadStartedAt;
88312
88803
  let storeReadEndedAt;
@@ -88688,10 +89179,10 @@ var init_ai_runner = __esm({
88688
89179
  const safeMessageId = encodeURIComponent(request.messageId);
88689
89180
  if (request.source === "job-dispatch") {
88690
89181
  const safeJobId = encodeURIComponent(request.jobId ?? "unknown");
88691
- return (0, import_node_path16.join)(this.logsDir, `ai-${safeJobId}-${safeMessageId}.log`);
89182
+ return (0, import_node_path17.join)(this.logsDir, `ai-${safeJobId}-${safeMessageId}.log`);
88692
89183
  }
88693
89184
  const safeSessionKey = encodeURIComponent(request.sessionKey);
88694
- return (0, import_node_path16.join)(this.logsDir, `ai-session-${safeSessionKey}-${safeMessageId}.log`);
89185
+ return (0, import_node_path17.join)(this.logsDir, `ai-session-${safeSessionKey}-${safeMessageId}.log`);
88695
89186
  }
88696
89187
  readRunAiSessionId(provider, request, file, sessionMeta) {
88697
89188
  if (request.source === "job-dispatch" && request.jobId) {
@@ -88845,7 +89336,7 @@ var init_ai_runner = __esm({
88845
89336
  process.env.OKX_AGENT_TASK_AI_CWD,
88846
89337
  this.sessionStore.getSetting("ai_working_dir"),
88847
89338
  safeProcessCwd(),
88848
- (0, import_node_os4.homedir)(),
89339
+ (0, import_node_os5.homedir)(),
88849
89340
  this.homeDir
88850
89341
  ];
88851
89342
  return candidates.find((candidate) => !!candidate && isDirectory(candidate)) ?? this.homeDir;
@@ -89002,7 +89493,7 @@ var init_ai_runner = __esm({
89002
89493
  async appendLlmLog(entry) {
89003
89494
  try {
89004
89495
  ensureTaskDir(this.logsDir);
89005
- await (0, import_promises5.appendFile)((0, import_node_path16.join)(this.logsDir, "llm.log"), formatLlmLogEntry(entry), "utf8");
89496
+ await (0, import_promises5.appendFile)((0, import_node_path17.join)(this.logsDir, "llm.log"), formatLlmLogEntry(entry), "utf8");
89006
89497
  } catch (err2) {
89007
89498
  errorWithTimestamp("[okx-agent-task] failed to append llm.log:", err2);
89008
89499
  }
@@ -91133,12 +91624,12 @@ async function runListenerWithLock(options, paths) {
91133
91624
  }));
91134
91625
  }
91135
91626
  });
91136
- service.setPluginVersion("0.0.15");
91627
+ service.setPluginVersion("0.0.16-beta-d0ec14bc63-260623110312");
91137
91628
  await service.init();
91138
91629
  const pluginVersionStatus = service.pluginVersionStatus;
91139
91630
  if (pluginVersionStatus.unavailable) {
91140
91631
  throw new Error(
91141
- `@okxweb3/a2a-node v${"0.0.15"} is below the required minimum v${pluginVersionStatus.minVersion}`
91632
+ `@okxweb3/a2a-node v${"0.0.16-beta-d0ec14bc63-260623110312"} is below the required minimum v${pluginVersionStatus.minVersion}`
91142
91633
  );
91143
91634
  }
91144
91635
  const systemConfig = service.getSystemConfig();
@@ -91156,7 +91647,7 @@ async function runListenerWithLock(options, paths) {
91156
91647
  onchainosAgentId: "*",
91157
91648
  reason: "system-config missing sentryDsn",
91158
91649
  pluginId: "@okxweb3/a2a-node",
91159
- pluginVersion: "0.0.15"
91650
+ pluginVersion: "0.0.16-beta-d0ec14bc63-260623110312"
91160
91651
  });
91161
91652
  }
91162
91653
  logWithTimestamp(
@@ -91350,9 +91841,9 @@ var init_listener = __esm({
91350
91841
 
91351
91842
  // ../core/src/file-upload-safety.ts
91352
91843
  function getUnsafeFileUploadReason(filePath, sensitiveUploadReg = []) {
91353
- const expanded = (0, import_node_path17.resolve)(expandHome(filePath));
91354
- const target = (0, import_node_fs13.realpathSync)(expanded);
91355
- const targetName = (0, import_node_path17.basename)(target);
91844
+ const expanded = (0, import_node_path18.resolve)(expandHome(filePath));
91845
+ const target = (0, import_node_fs14.realpathSync)(expanded);
91846
+ const targetName = (0, import_node_path18.basename)(target);
91356
91847
  if (targetName === ".env" || targetName.startsWith(".env.")) {
91357
91848
  return ".env";
91358
91849
  }
@@ -91360,18 +91851,18 @@ function getUnsafeFileUploadReason(filePath, sensitiveUploadReg = []) {
91360
91851
  if (configuredRule) {
91361
91852
  return `SENSITIVE_UPLOAD_REG:${configuredRule}`;
91362
91853
  }
91363
- const home = safeRealpath((0, import_node_os5.homedir)());
91854
+ const home = safeRealpath((0, import_node_os6.homedir)());
91364
91855
  if (!home) {
91365
91856
  return null;
91366
91857
  }
91367
91858
  for (const dir of SENSITIVE_HOME_DIRS) {
91368
- const sensitiveDir = safeRealpath((0, import_node_path17.join)(home, dir));
91859
+ const sensitiveDir = safeRealpath((0, import_node_path18.join)(home, dir));
91369
91860
  if (sensitiveDir && isPathInside(target, sensitiveDir)) {
91370
91861
  return `~/${dir}`;
91371
91862
  }
91372
91863
  }
91373
91864
  for (const file of SENSITIVE_HOME_FILES) {
91374
- const sensitiveFile = safeRealpath((0, import_node_path17.join)(home, file));
91865
+ const sensitiveFile = safeRealpath((0, import_node_path18.join)(home, file));
91375
91866
  if (sensitiveFile && target === sensitiveFile) {
91376
91867
  return `~/${file}`;
91377
91868
  }
@@ -91397,29 +91888,29 @@ function matchSensitiveUploadReg(paths, patterns) {
91397
91888
  }
91398
91889
  function expandHome(filePath) {
91399
91890
  if (filePath === "~") {
91400
- return (0, import_node_os5.homedir)();
91891
+ return (0, import_node_os6.homedir)();
91401
91892
  }
91402
- if (filePath.startsWith(`~${import_node_path17.sep}`)) {
91403
- return (0, import_node_path17.join)((0, import_node_os5.homedir)(), filePath.slice(2));
91893
+ if (filePath.startsWith(`~${import_node_path18.sep}`)) {
91894
+ return (0, import_node_path18.join)((0, import_node_os6.homedir)(), filePath.slice(2));
91404
91895
  }
91405
91896
  return filePath;
91406
91897
  }
91407
91898
  function safeRealpath(path) {
91408
- if (!(0, import_node_fs13.existsSync)(path)) {
91899
+ if (!(0, import_node_fs14.existsSync)(path)) {
91409
91900
  return null;
91410
91901
  }
91411
- return (0, import_node_fs13.realpathSync)(path);
91902
+ return (0, import_node_fs14.realpathSync)(path);
91412
91903
  }
91413
91904
  function isPathInside(target, dir) {
91414
- return target === dir || target.startsWith(`${dir}${import_node_path17.sep}`);
91905
+ return target === dir || target.startsWith(`${dir}${import_node_path18.sep}`);
91415
91906
  }
91416
- var import_node_fs13, import_node_os5, import_node_path17, SENSITIVE_HOME_DIRS, SENSITIVE_HOME_FILES, UNSAFE_FILE_UPLOAD_MESSAGE;
91907
+ var import_node_fs14, import_node_os6, import_node_path18, SENSITIVE_HOME_DIRS, SENSITIVE_HOME_FILES, UNSAFE_FILE_UPLOAD_MESSAGE;
91417
91908
  var init_file_upload_safety = __esm({
91418
91909
  "../core/src/file-upload-safety.ts"() {
91419
91910
  "use strict";
91420
- import_node_fs13 = require("node:fs");
91421
- import_node_os5 = require("node:os");
91422
- import_node_path17 = require("node:path");
91911
+ import_node_fs14 = require("node:fs");
91912
+ import_node_os6 = require("node:os");
91913
+ import_node_path18 = require("node:path");
91423
91914
  SENSITIVE_HOME_DIRS = [
91424
91915
  ".ssh",
91425
91916
  ".gnupg",
@@ -91427,7 +91918,7 @@ var init_file_upload_safety = __esm({
91427
91918
  ".azure",
91428
91919
  ".kube",
91429
91920
  ".docker",
91430
- (0, import_node_path17.join)(".config", "gcloud")
91921
+ (0, import_node_path18.join)(".config", "gcloud")
91431
91922
  ];
91432
91923
  SENSITIVE_HOME_FILES = [
91433
91924
  ".npmrc",
@@ -91489,7 +91980,7 @@ function hasHelpFlag(args) {
91489
91980
  return args.some((arg) => arg === "-h" || arg === "--help" || arg === "help");
91490
91981
  }
91491
91982
  async function uploadFile(params) {
91492
- const filename = params.filename || (0, import_node_path18.basename)(params.filePath);
91983
+ const filename = params.filename || (0, import_node_path19.basename)(params.filePath);
91493
91984
  const mimeType = params.mimeType || "application/octet-stream";
91494
91985
  const uploadConfig = readUploadSystemConfig();
91495
91986
  const unsafeReason = getUnsafeFileUploadReason(params.filePath, uploadConfig.sensitiveUploadReg);
@@ -91505,16 +91996,16 @@ async function uploadFile(params) {
91505
91996
  return;
91506
91997
  }
91507
91998
  const maxFileSizeBytes = uploadConfig.maxFileSizeBytes;
91508
- const fileSize = (0, import_node_fs14.statSync)(params.filePath).size;
91999
+ const fileSize = (0, import_node_fs15.statSync)(params.filePath).size;
91509
92000
  if (fileSize > maxFileSizeBytes) {
91510
92001
  throw new Error(formatFileTooLargeMessage(maxFileSizeBytes));
91511
92002
  }
91512
- const data = (0, import_node_fs14.readFileSync)(params.filePath);
92003
+ const data = (0, import_node_fs15.readFileSync)(params.filePath);
91513
92004
  const attachment = { filename, mimeType, data: new Uint8Array(data) };
91514
92005
  const encrypted = await RemoteAttachmentCodec.encodeEncrypted(attachment, new AttachmentCodec());
91515
92006
  ensureFileDirs();
91516
- const encryptedPath = (0, import_node_path18.resolve)(FILE_WORK_DIR, `${(0, import_node_crypto11.randomUUID)()}.enc`);
91517
- (0, import_node_fs14.writeFileSync)(encryptedPath, encrypted.payload);
92007
+ const encryptedPath = (0, import_node_path19.resolve)(FILE_WORK_DIR, `${(0, import_node_crypto11.randomUUID)()}.enc`);
92008
+ (0, import_node_fs15.writeFileSync)(encryptedPath, encrypted.payload);
91518
92009
  try {
91519
92010
  const stdout = runOnchainos([
91520
92011
  "agent",
@@ -91550,14 +92041,14 @@ async function uploadFile(params) {
91550
92041
  }, null, 2));
91551
92042
  } finally {
91552
92043
  try {
91553
- (0, import_node_fs14.unlinkSync)(encryptedPath);
92044
+ (0, import_node_fs15.unlinkSync)(encryptedPath);
91554
92045
  } catch {
91555
92046
  }
91556
92047
  }
91557
92048
  }
91558
92049
  async function downloadFile(params) {
91559
92050
  ensureFileDirs();
91560
- const encryptedPath = (0, import_node_path18.resolve)(FILE_WORK_DIR, `${(0, import_node_crypto11.randomUUID)()}.enc`);
92051
+ const encryptedPath = (0, import_node_path19.resolve)(FILE_WORK_DIR, `${(0, import_node_crypto11.randomUUID)()}.enc`);
91561
92052
  try {
91562
92053
  const stdout = runOnchainos([
91563
92054
  "agent",
@@ -91581,7 +92072,7 @@ async function downloadFile(params) {
91581
92072
  }));
91582
92073
  throw new Error(`file download failed: ${stdout}`);
91583
92074
  }
91584
- const payload = new Uint8Array((0, import_node_fs14.readFileSync)(encryptedPath));
92075
+ const payload = new Uint8Array((0, import_node_fs15.readFileSync)(encryptedPath));
91585
92076
  const digestBytes = new Uint8Array(await import_node_crypto11.webcrypto.subtle.digest("SHA-256", payload));
91586
92077
  const actualDigest = Array.from(digestBytes).map((byte) => byte.toString(16).padStart(2, "0")).join("");
91587
92078
  if (actualDigest !== params.digest) {
@@ -91593,12 +92084,12 @@ async function downloadFile(params) {
91593
92084
  const outputFilename = params.filename || attachment.filename || `${(0, import_node_crypto11.randomUUID)()}.bin`;
91594
92085
  const outputDir = DOWNLOADS_DIR;
91595
92086
  ensureA2aTaskDir(outputDir);
91596
- const outputPath = (0, import_node_path18.resolve)(outputDir, (0, import_node_path18.basename)(outputFilename));
91597
- (0, import_node_fs14.writeFileSync)(outputPath, attachment.data);
92087
+ const outputPath = (0, import_node_path19.resolve)(outputDir, (0, import_node_path19.basename)(outputFilename));
92088
+ (0, import_node_fs15.writeFileSync)(outputPath, attachment.data);
91598
92089
  console.log(outputPath);
91599
92090
  } finally {
91600
92091
  try {
91601
- (0, import_node_fs14.unlinkSync)(encryptedPath);
92092
+ (0, import_node_fs15.unlinkSync)(encryptedPath);
91602
92093
  } catch {
91603
92094
  }
91604
92095
  }
@@ -91694,7 +92185,7 @@ function readUploadSystemConfig() {
91694
92185
  const res = parseCliJson2(stdout, "system-config");
91695
92186
  if (res.data && typeof res.data === "object") {
91696
92187
  ensureA2aTaskDir(OKX_A2A_PATHS.xmtpDir);
91697
- (0, import_node_fs14.writeFileSync)(SYSTEM_CONFIG_PATH, JSON.stringify(res.data));
92188
+ (0, import_node_fs15.writeFileSync)(SYSTEM_CONFIG_PATH, JSON.stringify(res.data));
91698
92189
  }
91699
92190
  return parseUploadSystemConfig(res.data ?? {});
91700
92191
  } catch {
@@ -91717,10 +92208,10 @@ function fileCliSentryExtra(operation, reason, extra = {}) {
91717
92208
  }
91718
92209
  function readSystemConfigFromCache() {
91719
92210
  try {
91720
- if (!(0, import_node_fs14.existsSync)(SYSTEM_CONFIG_PATH)) {
92211
+ if (!(0, import_node_fs15.existsSync)(SYSTEM_CONFIG_PATH)) {
91721
92212
  return null;
91722
92213
  }
91723
- return JSON.parse((0, import_node_fs14.readFileSync)(SYSTEM_CONFIG_PATH, "utf8"));
92214
+ return JSON.parse((0, import_node_fs15.readFileSync)(SYSTEM_CONFIG_PATH, "utf8"));
91724
92215
  } catch {
91725
92216
  return null;
91726
92217
  }
@@ -91754,14 +92245,14 @@ function readRequiredOption(args, name2) {
91754
92245
  }
91755
92246
  return value;
91756
92247
  }
91757
- var import_node_child_process6, import_node_crypto11, import_node_fs14, import_node_path18, import_proto4, OKX_A2A_PATHS, OKX_A2A_HOME_DIR, FILE_WORK_DIR, DOWNLOADS_DIR, SYSTEM_CONFIG_PATH;
92248
+ var import_node_child_process6, import_node_crypto11, import_node_fs15, import_node_path19, import_proto4, OKX_A2A_PATHS, OKX_A2A_HOME_DIR, FILE_WORK_DIR, DOWNLOADS_DIR, SYSTEM_CONFIG_PATH;
91758
92249
  var init_file_cli = __esm({
91759
92250
  "src/file-cli.ts"() {
91760
92251
  "use strict";
91761
92252
  import_node_child_process6 = require("node:child_process");
91762
92253
  import_node_crypto11 = require("node:crypto");
91763
- import_node_fs14 = require("node:fs");
91764
- import_node_path18 = require("node:path");
92254
+ import_node_fs15 = require("node:fs");
92255
+ import_node_path19 = require("node:path");
91765
92256
  init_dist6();
91766
92257
  import_proto4 = __toESM(require_node3());
91767
92258
  init_a2a_paths();
@@ -91772,7 +92263,7 @@ var init_file_cli = __esm({
91772
92263
  OKX_A2A_HOME_DIR = OKX_A2A_PATHS.homeDir;
91773
92264
  FILE_WORK_DIR = process.env.OKX_A2A_FILE_WORK_DIR || OKX_A2A_PATHS.filesDir;
91774
92265
  DOWNLOADS_DIR = process.env.OKX_A2A_DOWNLOADS_DIR || OKX_A2A_PATHS.downloadsDir;
91775
- SYSTEM_CONFIG_PATH = (0, import_node_path18.resolve)(OKX_A2A_PATHS.xmtpDir, "system-config.json");
92266
+ SYSTEM_CONFIG_PATH = (0, import_node_path19.resolve)(OKX_A2A_PATHS.xmtpDir, "system-config.json");
91776
92267
  }
91777
92268
  });
91778
92269
 
@@ -92268,7 +92759,7 @@ function readJobId(parsed) {
92268
92759
  return envJobId;
92269
92760
  }
92270
92761
  const sessionKey = readCurrentSessionKeyFromEnv();
92271
- return sessionKey ? inferJobIdFromSessionKey2(sessionKey) : null;
92762
+ return sessionKey ? inferJobIdFromSessionKey3(sessionKey) : null;
92272
92763
  }
92273
92764
  function assertNoUserSessionKey(parsed, subcommand) {
92274
92765
  if (parsed.options.has("session-key")) {
@@ -92278,7 +92769,7 @@ function assertNoUserSessionKey(parsed, subcommand) {
92278
92769
  }
92279
92770
  }
92280
92771
  function readCurrentSessionKeyFromEnv() {
92281
- return normalizeOptionalText2(process.env.OKX_A2A_CURRENT_SESSION_KEY);
92772
+ return normalizeOptionalText2(process.env.OKX_A2A_CURRENT_SESSION_KEY) ?? normalizeOptionalText2(process.env.OKX_A2A_CURRENT_GATEWAY_SESSION_KEY);
92282
92773
  }
92283
92774
  function readProviderFilter(store, parsed, jobId) {
92284
92775
  if (parsed.flags.has("all-providers")) {
@@ -92428,7 +92919,7 @@ function isHermesRouteBindingDebugEnabled() {
92428
92919
  const value = process.env.OKX_A2A_DEBUG_HERMES_ROUTE_BINDING ?? "";
92429
92920
  return value === "1" || value.toLowerCase() === "true";
92430
92921
  }
92431
- function inferJobIdFromSessionKey2(sessionKey) {
92922
+ function inferJobIdFromSessionKey3(sessionKey) {
92432
92923
  const jobPrefix = /^job:([^:]+):/.exec(sessionKey);
92433
92924
  if (jobPrefix?.[1]) {
92434
92925
  return normalizeOptionalText2(safeDecodeURIComponent2(jobPrefix[1]));
@@ -92437,6 +92928,14 @@ function inferJobIdFromSessionKey2(sessionKey) {
92437
92928
  if (backup?.[1]) {
92438
92929
  return normalizeOptionalText2(safeDecodeURIComponent2(backup[1]));
92439
92930
  }
92931
+ const gatewayBackup = /(?:^|:)backup:([^:&]+)/.exec(sessionKey);
92932
+ if (gatewayBackup?.[1]) {
92933
+ return normalizeOptionalText2(safeDecodeURIComponent2(gatewayBackup[1]));
92934
+ }
92935
+ const gatewayJob = /(?:^|[?&:])job=([^:&]+)/.exec(sessionKey);
92936
+ if (gatewayJob?.[1]) {
92937
+ return normalizeOptionalText2(safeDecodeURIComponent2(gatewayJob[1]));
92938
+ }
92440
92939
  return null;
92441
92940
  }
92442
92941
  function safeDecodeURIComponent2(value) {
@@ -92518,6 +93017,7 @@ async function handleSessionCommand(args) {
92518
93017
  const provider = resolveSessionLifecycleProvider(store, input.jobId);
92519
93018
  if (provider === "openclaw") {
92520
93019
  usedOpenClawGateway = true;
93020
+ bindOpenClawGatewayRouteFromEnv(store, { jobId: input.jobId });
92521
93021
  await createOutboundBehavior(provider, { store }).createSession({
92522
93022
  sessionKey: input.sessionKey,
92523
93023
  jobId: input.jobId,
@@ -92591,7 +93091,7 @@ async function handleSessionCommand(args) {
92591
93091
  const exactExisting = exactSessionKey ? store.getSession(exactSessionKey) : null;
92592
93092
  const provider = resolveSessionDeleteProvider(
92593
93093
  store,
92594
- exactExisting?.jobId ?? (exactSessionKey ? inferJobIdFromSessionKey3(exactSessionKey) : jobId)
93094
+ exactExisting?.jobId ?? (exactSessionKey ? inferJobIdFromSessionKey4(exactSessionKey) : jobId)
92595
93095
  );
92596
93096
  if (provider === "openclaw") {
92597
93097
  usedOpenClawGateway = true;
@@ -93272,7 +93772,7 @@ function resolveSendSessionTargets(parsed, store) {
93272
93772
  if (sessionKey) {
93273
93773
  return [{
93274
93774
  sessionKey,
93275
- jobId: parsed.options.get("job-id") ?? inferJobIdFromSessionKey3(sessionKey),
93775
+ jobId: parsed.options.get("job-id") ?? inferJobIdFromSessionKey4(sessionKey),
93276
93776
  agentId: parsed.options.get("agent-id") ?? parsed.options.get("my-agent-id") ?? null,
93277
93777
  toAgentId: null
93278
93778
  }];
@@ -93353,7 +93853,7 @@ function parseModernSessionKey(sessionKey) {
93353
93853
  toAgentId: decodeURIComponent(parts[5])
93354
93854
  };
93355
93855
  }
93356
- function inferJobIdFromSessionKey3(sessionKey) {
93856
+ function inferJobIdFromSessionKey4(sessionKey) {
93357
93857
  const modern = parseModernSessionKey(sessionKey);
93358
93858
  if (modern?.jobId) {
93359
93859
  return modern.jobId;
@@ -93441,6 +93941,7 @@ var init_session_cli = __esm({
93441
93941
  init_ai_dispatch_queue();
93442
93942
  init_ai_provider();
93443
93943
  init_outbound_behavior();
93944
+ init_openclaw_route();
93444
93945
  init_openclaw_gateway();
93445
93946
  init_sentry_logger();
93446
93947
  init_openclaw_gateway_config();
@@ -93912,7 +94413,7 @@ function detectSetupTarget() {
93912
94413
  }
93913
94414
  const gatewayProviders = [
93914
94415
  ...commandExists("openclaw") ? ["openclaw"] : [],
93915
- ...commandExists("hermes") || (0, import_node_fs15.existsSync)((0, import_node_path19.join)(process.env.HERMES_HOME ?? (0, import_node_path19.join)((0, import_node_os6.homedir)(), ".hermes"))) ? ["hermes"] : []
94416
+ ...commandExists("hermes") || (0, import_node_fs16.existsSync)((0, import_node_path20.join)(process.env.HERMES_HOME ?? (0, import_node_path20.join)((0, import_node_os7.homedir)(), ".hermes"))) ? ["hermes"] : []
93916
94417
  ];
93917
94418
  if (gatewayProviders.length === 1) {
93918
94419
  return gatewayProviders[0];
@@ -93969,7 +94470,7 @@ async function getCurrentNodeCliVersion() {
93969
94470
  return await getGlobalNpmPackageVersion(UPDATE_PACKAGES.node) ?? getBundledNodeCliVersion();
93970
94471
  }
93971
94472
  function getBundledNodeCliVersion() {
93972
- return true ? "0.0.15" : null;
94473
+ return true ? "0.0.16-beta-d0ec14bc63-260623110312" : null;
93973
94474
  }
93974
94475
  function readConfiguredAiProvider() {
93975
94476
  const explicit = process.env.OKX_AGENT_TASK_AI_CLI ?? process.env.OKX_A2A_AI_PROVIDER;
@@ -94039,17 +94540,17 @@ async function updateHermes(release, options) {
94039
94540
  const label = options.label ?? "update";
94040
94541
  assertNotRunningInsideGateway("hermes");
94041
94542
  const spec = buildNpmPackageSpec("hermes", release);
94042
- const workDir = await (0, import_promises6.mkdtemp)((0, import_node_path19.join)((0, import_node_os6.tmpdir)(), `okx-a2a-${label}-hermes-`));
94543
+ const workDir = await (0, import_promises6.mkdtemp)((0, import_node_path20.join)((0, import_node_os7.tmpdir)(), `okx-a2a-${label}-hermes-`));
94043
94544
  try {
94044
94545
  console.log(`[${label}] downloading ${spec}`);
94045
94546
  const npmTarball = await npmPack(spec, workDir);
94046
- const npmPackageDir = (0, import_node_path19.join)(workDir, "npm-package");
94547
+ const npmPackageDir = (0, import_node_path20.join)(workDir, "npm-package");
94047
94548
  await runCommand("tar", ["-xzf", npmTarball, "-C", npmPackageDir], { ensureDir: npmPackageDir });
94048
- const pluginTarball = await findHermesPluginTarball((0, import_node_path19.join)(npmPackageDir, "package", "dist"));
94049
- const pluginDir = (0, import_node_path19.join)(workDir, "plugin");
94549
+ const pluginTarball = await findHermesPluginTarball((0, import_node_path20.join)(npmPackageDir, "package", "dist"));
94550
+ const pluginDir = (0, import_node_path20.join)(workDir, "plugin");
94050
94551
  await runCommand("tar", ["-xzf", pluginTarball, "-C", pluginDir], { ensureDir: pluginDir });
94051
94552
  const unpackedPluginDir = await findFirstDirectory(pluginDir);
94052
- const installer = (0, import_node_path19.join)(unpackedPluginDir, "scripts", "install-or-upgrade.sh");
94553
+ const installer = (0, import_node_path20.join)(unpackedPluginDir, "scripts", "install-or-upgrade.sh");
94053
94554
  console.log(`[${label}] running ${installer}`);
94054
94555
  await runCommand("bash", [installer, ...options.restart ? ["--restart"] : []], { cwd: unpackedPluginDir });
94055
94556
  await normalizeHermesOkxA2aPluginConfig();
@@ -94085,7 +94586,7 @@ async function ensureHermesOkxA2aPluginConfig(configFile = resolveHermesConfigPa
94085
94586
  content3 = await (0, import_promises6.readFile)(configFile, "utf8");
94086
94587
  } catch (error) {
94087
94588
  if (isNodeError(error) && error.code === "ENOENT") {
94088
- await (0, import_promises6.mkdir)((0, import_node_path19.resolve)(configFile, ".."), { recursive: true });
94589
+ await (0, import_promises6.mkdir)((0, import_node_path20.resolve)(configFile, ".."), { recursive: true });
94089
94590
  await (0, import_promises6.writeFile)(configFile, "plugins:\n enabled:\n - okx-a2a\n");
94090
94591
  console.log(`[update] added Hermes plugins.enabled okx-a2a entry in ${configFile}`);
94091
94592
  return true;
@@ -94245,7 +94746,7 @@ function addHermesOkxA2aEnabled(content3) {
94245
94746
  return `${lines.join("\n")}${trailingNewline ? "\n" : ""}`;
94246
94747
  }
94247
94748
  function resolveHermesConfigPath() {
94248
- return (0, import_node_path19.join)(process.env.HERMES_HOME ?? (0, import_node_path19.join)((0, import_node_os6.homedir)(), ".hermes"), "config.yaml");
94749
+ return (0, import_node_path20.join)(process.env.HERMES_HOME ?? (0, import_node_path20.join)((0, import_node_os7.homedir)(), ".hermes"), "config.yaml");
94249
94750
  }
94250
94751
  function lineIndent(line) {
94251
94752
  const match = line.match(/^\s*/);
@@ -94318,7 +94819,7 @@ async function isGatewayPluginInstalled(target) {
94318
94819
  if (target === "openclaw") {
94319
94820
  return (await getInstalledOpenClawPluginInfo()).installed;
94320
94821
  }
94321
- if ((0, import_node_fs15.existsSync)((0, import_node_path19.join)(process.env.HERMES_HOME ?? (0, import_node_path19.join)((0, import_node_os6.homedir)(), ".hermes"), "plugins", "platforms", "okx-a2a", "plugin.yaml"))) {
94822
+ if ((0, import_node_fs16.existsSync)((0, import_node_path20.join)(process.env.HERMES_HOME ?? (0, import_node_path20.join)((0, import_node_os7.homedir)(), ".hermes"), "plugins", "platforms", "okx-a2a", "plugin.yaml"))) {
94322
94823
  return true;
94323
94824
  }
94324
94825
  return await isGlobalNpmPackageInstalled(UPDATE_PACKAGES.hermes);
@@ -94412,7 +94913,7 @@ function parsePackageVersionFromText(output4) {
94412
94913
  return output4.match(/@okxweb3\/a2a-openclaw@([0-9A-Za-z.+-]+)/)?.[1] ?? null;
94413
94914
  }
94414
94915
  async function getInstalledHermesPluginVersion() {
94415
- const pluginYaml = (0, import_node_path19.join)(process.env.HERMES_HOME ?? (0, import_node_path19.join)((0, import_node_os6.homedir)(), ".hermes"), "plugins", "platforms", "okx-a2a", "plugin.yaml");
94916
+ const pluginYaml = (0, import_node_path20.join)(process.env.HERMES_HOME ?? (0, import_node_path20.join)((0, import_node_os7.homedir)(), ".hermes"), "plugins", "platforms", "okx-a2a", "plugin.yaml");
94416
94917
  try {
94417
94918
  const content3 = await (0, import_promises6.readFile)(pluginYaml, "utf8");
94418
94919
  return parsePluginYamlVersion(content3);
@@ -94465,7 +94966,7 @@ async function npmPack(spec, destination) {
94465
94966
  if (!tarballName) {
94466
94967
  throw new Error(`Unable to detect npm pack tarball from output: ${output4.trim()}`);
94467
94968
  }
94468
- return (0, import_node_path19.resolve)(destination, (0, import_node_path19.basename)(tarballName));
94969
+ return (0, import_node_path20.resolve)(destination, (0, import_node_path20.basename)(tarballName));
94469
94970
  }
94470
94971
  async function findHermesPluginTarball(distDir) {
94471
94972
  const entries = await (0, import_promises6.readdir)(distDir);
@@ -94473,7 +94974,7 @@ async function findHermesPluginTarball(distDir) {
94473
94974
  if (!tarball) {
94474
94975
  throw new Error(`Hermes npm package did not contain dist/okx-a2a-hermes-plugin-*.tar.gz`);
94475
94976
  }
94476
- return (0, import_node_path19.join)(distDir, tarball);
94977
+ return (0, import_node_path20.join)(distDir, tarball);
94477
94978
  }
94478
94979
  async function findFirstDirectory(parent) {
94479
94980
  const entries = await (0, import_promises6.readdir)(parent, { withFileTypes: true });
@@ -94481,7 +94982,7 @@ async function findFirstDirectory(parent) {
94481
94982
  if (!dir) {
94482
94983
  throw new Error(`No unpacked plugin directory found under ${parent}`);
94483
94984
  }
94484
- return (0, import_node_path19.join)(parent, dir.name);
94985
+ return (0, import_node_path20.join)(parent, dir.name);
94485
94986
  }
94486
94987
  function readOption2(args, name2) {
94487
94988
  const index2 = args.indexOf(name2);
@@ -94588,15 +95089,15 @@ async function runCommandCaptureOptional(command, args) {
94588
95089
  });
94589
95090
  });
94590
95091
  }
94591
- var import_node_child_process7, import_node_fs15, import_promises6, import_node_os6, import_node_path19, UPDATE_PACKAGES, OPENCLAW_UNSAFE_INSTALL_FLAG, redirectCommandStdoutToStderr;
95092
+ var import_node_child_process7, import_node_fs16, import_promises6, import_node_os7, import_node_path20, UPDATE_PACKAGES, OPENCLAW_UNSAFE_INSTALL_FLAG, redirectCommandStdoutToStderr;
94592
95093
  var init_update_cli = __esm({
94593
95094
  "src/update-cli.ts"() {
94594
95095
  "use strict";
94595
95096
  import_node_child_process7 = require("node:child_process");
94596
- import_node_fs15 = require("node:fs");
95097
+ import_node_fs16 = require("node:fs");
94597
95098
  import_promises6 = require("node:fs/promises");
94598
- import_node_os6 = require("node:os");
94599
- import_node_path19 = require("node:path");
95099
+ import_node_os7 = require("node:os");
95100
+ import_node_path20 = require("node:path");
94600
95101
  init_ai_provider();
94601
95102
  init_ai_command();
94602
95103
  init_session_store();
@@ -94612,21 +95113,23 @@ var init_update_cli = __esm({
94612
95113
 
94613
95114
  // src/cli.ts
94614
95115
  var import_node_child_process8 = require("node:child_process");
94615
- var import_node_fs16 = require("node:fs");
94616
- var import_node_os7 = require("node:os");
94617
- var import_node_path20 = require("node:path");
95116
+ var import_node_fs17 = require("node:fs");
95117
+ var import_node_os8 = require("node:os");
95118
+ var import_node_path21 = require("node:path");
94618
95119
  init_daemon();
94619
95120
  init_command_store();
94620
95121
  init_file_store();
94621
95122
  init_ai_provider();
94622
95123
  init_session_store();
94623
95124
  init_outbound_behavior();
95125
+ init_openclaw_route();
94624
95126
  init_paths();
94625
95127
  init_task_config();
94626
95128
  init_sentry_logger();
94627
95129
  init_sentry_config();
95130
+ var CURRENT_GATEWAY_SESSION_KEYS_ENV2 = "OKX_A2A_CURRENT_GATEWAY_SESSION_KEYS";
94628
95131
  function printUsage2() {
94629
- console.log(`okx-a2a ${"0.0.15"}
95132
+ console.log(`okx-a2a ${"0.0.16-beta-d0ec14bc63-260623110312"}
94630
95133
 
94631
95134
  Usage:
94632
95135
  okx-a2a <command> [options]
@@ -94663,7 +95166,7 @@ Run \`okx-a2a <command> -h\` for command-specific help.
94663
95166
  `);
94664
95167
  }
94665
95168
  function printVersion() {
94666
- console.log("0.0.15");
95169
+ console.log("0.0.16-beta-d0ec14bc63-260623110312");
94667
95170
  }
94668
95171
  function printDaemonUsage() {
94669
95172
  console.log(`Usage: okx-a2a daemon <start|restart|stop|status> [options]
@@ -94941,7 +95444,7 @@ async function handleLogs(args) {
94941
95444
  return;
94942
95445
  }
94943
95446
  if (subcommand === "llm") {
94944
- await tailLogFile((0, import_node_path20.join)(paths.logsDir, "llm.log"));
95447
+ await tailLogFile((0, import_node_path21.join)(paths.logsDir, "llm.log"));
94945
95448
  return;
94946
95449
  }
94947
95450
  throw new Error("logs requires <server|llm>");
@@ -94992,11 +95495,39 @@ async function queueXmtpSend(args) {
94992
95495
  sessionAgentId,
94993
95496
  myAgentId: target.myAgentId,
94994
95497
  toAgentId: target.toAgentId,
94995
- toXmtpAddress: toXmtpAddress ?? target.toXmtpAddress
95498
+ toXmtpAddress: toXmtpAddress ?? target.toXmtpAddress,
95499
+ gatewaySessionKeys: readGatewaySessionKeysFromEnv()
94996
95500
  });
94997
95501
  await commands.submit(command);
94998
95502
  console.log(`queued xmtp-send command=${command.id} jobId=${target.jobId}`);
94999
95503
  }
95504
+ function readGatewaySessionKeysFromEnv(env = process.env) {
95505
+ const keys = /* @__PURE__ */ new Set();
95506
+ const list = env[CURRENT_GATEWAY_SESSION_KEYS_ENV2]?.trim();
95507
+ if (list) {
95508
+ try {
95509
+ const parsed = JSON.parse(list);
95510
+ if (Array.isArray(parsed)) {
95511
+ for (const item of parsed) {
95512
+ if (typeof item === "string" && item.trim()) {
95513
+ keys.add(item.trim());
95514
+ }
95515
+ }
95516
+ }
95517
+ } catch {
95518
+ for (const item of list.split(",")) {
95519
+ if (item.trim()) {
95520
+ keys.add(item.trim());
95521
+ }
95522
+ }
95523
+ }
95524
+ }
95525
+ const single = env.OKX_A2A_CURRENT_GATEWAY_SESSION_KEY?.trim();
95526
+ if (single) {
95527
+ keys.add(single);
95528
+ }
95529
+ return keys.size > 0 ? [...keys] : void 0;
95530
+ }
95000
95531
  function resolveXmtpSendTarget(input) {
95001
95532
  if (input.sessionKey) {
95002
95533
  if (input.jobId || input.toAgentId) {
@@ -95337,8 +95868,10 @@ async function dispatchRuntimeSwitchUserMessage(store, result) {
95337
95868
  return;
95338
95869
  }
95339
95870
  try {
95871
+ const sessionKey = result.provider === "openclaw" ? currentOpenClawGatewaySessionKey() ?? void 0 : void 0;
95340
95872
  await createOutboundBehavior(result.provider, { store }).dispatchUser({
95341
95873
  userContent: result.userMessage,
95874
+ ...sessionKey ? { sessionKey } : {},
95342
95875
  idempotencyKey: `runtime-switch:${result.provider}:${result.previousProvider ?? "none"}`
95343
95876
  });
95344
95877
  } catch (err2) {
@@ -95588,11 +96121,11 @@ function initDirectCliSentry() {
95588
96121
  }
95589
96122
  cliSentryInitAttempted = true;
95590
96123
  try {
95591
- const configPath = (0, import_node_path20.join)(resolveTaskHomeForSentryConfig(), "xmtp", "system-config.json");
95592
- if (!(0, import_node_fs16.existsSync)(configPath)) {
96124
+ const configPath = (0, import_node_path21.join)(resolveTaskHomeForSentryConfig(), "xmtp", "system-config.json");
96125
+ if (!(0, import_node_fs17.existsSync)(configPath)) {
95593
96126
  return;
95594
96127
  }
95595
- const config = JSON.parse((0, import_node_fs16.readFileSync)(configPath, "utf8"));
96128
+ const config = JSON.parse((0, import_node_fs17.readFileSync)(configPath, "utf8"));
95596
96129
  if (typeof config.sentryDsn !== "string" || !config.sentryDsn) {
95597
96130
  return;
95598
96131
  }
@@ -95610,13 +96143,13 @@ function resolveTaskHomeForSentryConfig() {
95610
96143
  return process.env.OKX_AGENT_TASK_HOME;
95611
96144
  }
95612
96145
  try {
95613
- const home = (0, import_node_os7.homedir)();
96146
+ const home = (0, import_node_os8.homedir)();
95614
96147
  if (home) {
95615
- return (0, import_node_path20.join)(home, ".okx-agent-task");
96148
+ return (0, import_node_path21.join)(home, ".okx-agent-task");
95616
96149
  }
95617
96150
  } catch {
95618
96151
  }
95619
- return (0, import_node_path20.resolve)(process.cwd(), ".okx-agent-task");
96152
+ return (0, import_node_path21.resolve)(process.cwd(), ".okx-agent-task");
95620
96153
  }
95621
96154
  function directCliSentryExtra(operation, extra = {}) {
95622
96155
  return {