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

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 +684 -166
  2. package/dist/index.js +504 -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-260623103149",
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-260623103149"}`,
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;
@@ -23717,11 +24037,20 @@ var init_outbound_behavior = __esm({
23717
24037
  });
23718
24038
  }
23719
24039
  async dispatchUser(input) {
24040
+ const routed = this.resolveUserGatewaySessionKey(input);
24041
+ if (routed) {
24042
+ await this.dispatchUserToGatewaySession(input, routed);
24043
+ return null;
24044
+ }
23720
24045
  errorWithTimestamp(
23721
24046
  `${GATEWAY_OUTBOUND_LOG_PREFIX} dispatchUser latestUserSessions jobId=${input.jobId ?? "(none)"} idempotencyKey=${input.idempotencyKey ?? "(none)"}`
23722
24047
  );
23723
24048
  try {
23724
- const result = await this.gateway.callDispatchUserToLatestSessions({ content: input.userContent });
24049
+ const result = await this.gateway.callDispatchUserToLatestSessions({
24050
+ content: input.userContent,
24051
+ ...input.jobId ? { jobId: input.jobId } : {},
24052
+ ...input.sessionKey ? { currentSessionKey: input.sessionKey } : {}
24053
+ });
23725
24054
  assertLatestUserFanoutDelivered("okx-a2a.dispatch_user", result);
23726
24055
  errorWithTimestamp(`${GATEWAY_OUTBOUND_LOG_PREFIX} dispatchUser latestUserSessions ok`);
23727
24056
  logger.info(LogEvent.USER_DISPATCHED, gatewayOutboundExtra("okx-a2a.dispatch_user", {
@@ -23759,14 +24088,90 @@ var init_outbound_behavior = __esm({
23759
24088
  }
23760
24089
  return null;
23761
24090
  }
24091
+ resolveUserGatewaySessionKey(input) {
24092
+ const routes = resolveOpenClawGatewayRoutes(this.sessionMetaStore, input);
24093
+ if (routes.length > 0) {
24094
+ return { sessionKeys: routes.map((route) => route.sessionKey), source: "stored_openclaw_routes" };
24095
+ }
24096
+ if (input.sessionKey?.startsWith("agent:")) {
24097
+ return isValidOpenClawGatewaySessionKey(input.sessionKey) ? { sessionKeys: [input.sessionKey], source: "explicit_gateway_session" } : null;
24098
+ }
24099
+ return null;
24100
+ }
24101
+ async dispatchUserToGatewaySession(input, routed) {
24102
+ const gatewaySessionKey = routed.sessionKeys.join(",");
24103
+ console.error(
24104
+ `${GATEWAY_OUTBOUND_LOG_PREFIX} dispatchUser routed sessionKey=${input.sessionKey ?? "(none)"} gatewaySessionKey=${gatewaySessionKey} source=${routed.source} jobId=${input.jobId ?? "(none)"} idempotencyKey=${input.idempotencyKey ?? "(none)"}`
24105
+ );
24106
+ try {
24107
+ const result = await this.gateway.callDispatchUserToLatestSessions({
24108
+ content: input.userContent,
24109
+ label: "okx-a2a",
24110
+ ...routed.source === "stored_openclaw_routes" ? { sessionKeys: routed.sessionKeys } : { sessionKey: routed.sessionKeys[0] }
24111
+ });
24112
+ assertLatestUserFanoutDelivered("okx-a2a.dispatch_user", result);
24113
+ console.error(`${GATEWAY_OUTBOUND_LOG_PREFIX} dispatchUser routed ok gatewaySessionKey=${gatewaySessionKey} source=${routed.source}`);
24114
+ logger.info(LogEvent.USER_DISPATCHED, gatewayOutboundExtra("okx-a2a.dispatch_user", {
24115
+ sessionKey: input.sessionKey ?? "",
24116
+ gatewaySessionKey,
24117
+ jobId: input.jobId ?? "",
24118
+ source: routed.source,
24119
+ status: "delivered"
24120
+ }));
24121
+ } catch (err2) {
24122
+ if (!this.store || !isRetryableOpenClawGatewayError(err2)) {
24123
+ logger.error(LogEvent.USER_DISPATCH_FAILED, err2 instanceof Error ? err2 : new Error(String(err2)), gatewayOutboundExtra("okx-a2a.dispatch_user", {
24124
+ sessionKey: input.sessionKey ?? "",
24125
+ gatewaySessionKey,
24126
+ jobId: input.jobId ?? "",
24127
+ source: routed.source,
24128
+ status: "failed"
24129
+ }));
24130
+ throw err2;
24131
+ }
24132
+ this.store.enqueuePendingGatewayDelivery({
24133
+ kind: "chat_inject",
24134
+ provider: this.provider,
24135
+ sessionKey: routed.sessionKeys[0] ?? "openclaw:routed-user-sessions",
24136
+ content: input.userContent,
24137
+ jobId: input.jobId ?? null,
24138
+ messageId: input.idempotencyKey ?? null
24139
+ });
24140
+ console.error(
24141
+ `${GATEWAY_OUTBOUND_LOG_PREFIX} dispatchUser routed buffered gatewaySessionKey=${gatewaySessionKey} source=${routed.source} idempotencyKey=${input.idempotencyKey ?? "(none)"}: ${err2 instanceof Error ? err2.message : String(err2)}`
24142
+ );
24143
+ logger.error(LogEvent.USER_DISPATCH_FAILED, err2 instanceof Error ? err2 : new Error(String(err2)), gatewayOutboundExtra("okx-a2a.dispatch_user", {
24144
+ sessionKey: input.sessionKey ?? "",
24145
+ gatewaySessionKey,
24146
+ jobId: input.jobId ?? "",
24147
+ source: routed.source,
24148
+ status: "buffered"
24149
+ }));
24150
+ logger.info(LogEvent.GATEWAY_DELIVERY_BUFFERED, gatewayOutboundExtra("okx-a2a.dispatch_user", {
24151
+ sessionKey: input.sessionKey ?? "",
24152
+ gatewaySessionKey,
24153
+ jobId: input.jobId ?? "",
24154
+ messageId: input.idempotencyKey ?? "",
24155
+ source: routed.source,
24156
+ status: "buffered"
24157
+ }));
24158
+ }
24159
+ }
23762
24160
  async promptUser(input) {
24161
+ const routed = this.resolveUserGatewaySessionKey(input);
24162
+ if (routed) {
24163
+ await this.promptUserToGatewaySession(input, routed);
24164
+ return null;
24165
+ }
23763
24166
  errorWithTimestamp(
23764
24167
  `${GATEWAY_OUTBOUND_LOG_PREFIX} promptUser latestUserSessions jobId=${input.jobId ?? "(none)"} idempotencyKey=${input.idempotencyKey ?? "(none)"}`
23765
24168
  );
23766
24169
  try {
23767
24170
  const result = await this.gateway.callPromptUserToLatestSessions({
23768
24171
  userContent: input.userContent,
23769
- llmContent: input.llmContent
24172
+ llmContent: input.llmContent,
24173
+ ...input.jobId ? { jobId: input.jobId } : {},
24174
+ ...input.sessionKey ? { currentSessionKey: input.sessionKey } : {}
23770
24175
  });
23771
24176
  assertLatestUserFanoutDelivered("okx-a2a.prompt_user", result);
23772
24177
  errorWithTimestamp(`${GATEWAY_OUTBOUND_LOG_PREFIX} promptUser latestUserSessions ok`);
@@ -23806,6 +24211,66 @@ var init_outbound_behavior = __esm({
23806
24211
  }
23807
24212
  return null;
23808
24213
  }
24214
+ async promptUserToGatewaySession(input, routed) {
24215
+ const gatewaySessionKey = routed.sessionKeys.join(",");
24216
+ console.error(
24217
+ `${GATEWAY_OUTBOUND_LOG_PREFIX} promptUser routed sessionKey=${input.sessionKey ?? "(none)"} gatewaySessionKey=${gatewaySessionKey} source=${routed.source} jobId=${input.jobId ?? "(none)"} idempotencyKey=${input.idempotencyKey ?? "(none)"}`
24218
+ );
24219
+ try {
24220
+ const result = await this.gateway.callPromptUserToLatestSessions({
24221
+ userContent: input.userContent,
24222
+ llmContent: input.llmContent,
24223
+ ...routed.source === "stored_openclaw_routes" ? { sessionKeys: routed.sessionKeys } : { sessionKey: routed.sessionKeys[0] }
24224
+ });
24225
+ assertLatestUserFanoutDelivered("okx-a2a.prompt_user", result);
24226
+ console.error(`${GATEWAY_OUTBOUND_LOG_PREFIX} promptUser routed ok gatewaySessionKey=${gatewaySessionKey} source=${routed.source}`);
24227
+ logger.info(LogEvent.PROMPT_USER_CHECKPOINT, gatewayOutboundExtra("routed_prompt_user", {
24228
+ sessionKey: input.sessionKey ?? "",
24229
+ gatewaySessionKey,
24230
+ jobId: input.jobId ?? "",
24231
+ source: routed.source,
24232
+ status: "delivered"
24233
+ }));
24234
+ } catch (err2) {
24235
+ if (!this.store || !isRetryableOpenClawGatewayError(err2)) {
24236
+ logger.error(LogEvent.PROMPT_USER_FAILED, err2 instanceof Error ? err2 : new Error(String(err2)), gatewayOutboundExtra("routed_prompt_user", {
24237
+ sessionKey: input.sessionKey ?? "",
24238
+ gatewaySessionKey,
24239
+ jobId: input.jobId ?? "",
24240
+ source: routed.source,
24241
+ status: "failed"
24242
+ }));
24243
+ throw err2;
24244
+ }
24245
+ this.store.enqueuePendingGatewayDelivery({
24246
+ kind: "chat_inject",
24247
+ provider: this.provider,
24248
+ sessionKey: routed.sessionKeys[0] ?? "openclaw:routed-user-sessions",
24249
+ content: input.userContent,
24250
+ llmContent: input.llmContent,
24251
+ jobId: input.jobId ?? null,
24252
+ messageId: input.idempotencyKey ?? null
24253
+ });
24254
+ console.error(
24255
+ `${GATEWAY_OUTBOUND_LOG_PREFIX} promptUser routed buffered gatewaySessionKey=${gatewaySessionKey} source=${routed.source} idempotencyKey=${input.idempotencyKey ?? "(none)"}: ${err2 instanceof Error ? err2.message : String(err2)}`
24256
+ );
24257
+ logger.error(LogEvent.PROMPT_USER_FAILED, err2 instanceof Error ? err2 : new Error(String(err2)), gatewayOutboundExtra("routed_prompt_user", {
24258
+ sessionKey: input.sessionKey ?? "",
24259
+ gatewaySessionKey,
24260
+ jobId: input.jobId ?? "",
24261
+ source: routed.source,
24262
+ status: "buffered"
24263
+ }));
24264
+ logger.info(LogEvent.GATEWAY_DELIVERY_BUFFERED, gatewayOutboundExtra("routed_prompt_user", {
24265
+ sessionKey: input.sessionKey ?? "",
24266
+ gatewaySessionKey,
24267
+ jobId: input.jobId ?? "",
24268
+ messageId: input.idempotencyKey ?? "",
24269
+ source: routed.source,
24270
+ status: "buffered"
24271
+ }));
24272
+ }
24273
+ }
23809
24274
  };
23810
24275
  }
23811
24276
  });
@@ -23823,23 +24288,23 @@ function resolveAiPermissionPreset(options = {}) {
23823
24288
  }
23824
24289
  function readAiPermissionPresetFromConfig(homeDir) {
23825
24290
  const configPath = resolveTaskConfigPath(homeDir);
23826
- if (!(0, import_node_fs8.existsSync)(configPath)) {
24291
+ if (!(0, import_node_fs9.existsSync)(configPath)) {
23827
24292
  return null;
23828
24293
  }
23829
- const raw = readSimpleTomlStringValue((0, import_node_fs8.readFileSync)(configPath, "utf8"), "ai.permissions", "preset");
24294
+ const raw = readSimpleTomlStringValue((0, import_node_fs9.readFileSync)(configPath, "utf8"), "ai.permissions", "preset");
23830
24295
  return raw ? normalizeAiPermissionPreset(raw, configPath) : null;
23831
24296
  }
23832
24297
  function writeAiPermissionPresetToConfig(homeDir, preset) {
23833
24298
  const normalized = normalizeAiPermissionPreset(preset, "permission preset");
23834
24299
  ensureTaskDir(homeDir);
23835
24300
  const configPath = resolveTaskConfigPath(homeDir);
23836
- const current = (0, import_node_fs8.existsSync)(configPath) ? (0, import_node_fs8.readFileSync)(configPath, "utf8") : "";
24301
+ const current = (0, import_node_fs9.existsSync)(configPath) ? (0, import_node_fs9.readFileSync)(configPath, "utf8") : "";
23837
24302
  const next = upsertSimpleTomlStringValue(current, "ai.permissions", "preset", normalized);
23838
- (0, import_node_fs8.writeFileSync)(configPath, next, "utf8");
24303
+ (0, import_node_fs9.writeFileSync)(configPath, next, "utf8");
23839
24304
  return normalized;
23840
24305
  }
23841
24306
  function resolveTaskConfigPath(homeDir) {
23842
- return (0, import_node_path11.join)(homeDir, "config.toml");
24307
+ return (0, import_node_path12.join)(homeDir, "config.toml");
23843
24308
  }
23844
24309
  function normalizeAiPermissionPreset(value, source) {
23845
24310
  const normalized = value.trim().toLowerCase();
@@ -23912,12 +24377,12 @@ function upsertSimpleTomlStringValue(text, section, key, value) {
23912
24377
  function escapeRegExp(value) {
23913
24378
  return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
23914
24379
  }
23915
- var import_node_fs8, import_node_path11, AI_PERMISSION_PRESETS, DEFAULT_AI_PERMISSION_PRESET;
24380
+ var import_node_fs9, import_node_path12, AI_PERMISSION_PRESETS, DEFAULT_AI_PERMISSION_PRESET;
23916
24381
  var init_task_config = __esm({
23917
24382
  "src/task-config.ts"() {
23918
24383
  "use strict";
23919
- import_node_fs8 = require("node:fs");
23920
- import_node_path11 = require("node:path");
24384
+ import_node_fs9 = require("node:fs");
24385
+ import_node_path12 = require("node:path");
23921
24386
  init_paths();
23922
24387
  AI_PERMISSION_PRESETS = ["bypass", "auto"];
23923
24388
  DEFAULT_AI_PERMISSION_PRESET = "bypass";
@@ -23932,7 +24397,7 @@ var init_sentry_config = __esm({
23932
24397
  environment = process.env.SENTRY_ENV === "dev" ? "dev" : "prod";
23933
24398
  SENTRY_CONFIG = {
23934
24399
  projectName: "okx/openclaw-okx-a2a-extension",
23935
- release: "0.0.15",
24400
+ release: "0.0.16-beta-d0ec14bc63-260623103149",
23936
24401
  environment
23937
24402
  };
23938
24403
  }
@@ -23981,7 +24446,7 @@ function extractExecutablePath(stdout) {
23981
24446
  }
23982
24447
  function isExecutable2(path) {
23983
24448
  try {
23984
- (0, import_node_fs9.accessSync)(path, import_node_fs9.constants.X_OK);
24449
+ (0, import_node_fs10.accessSync)(path, import_node_fs10.constants.X_OK);
23985
24450
  return true;
23986
24451
  } catch {
23987
24452
  return false;
@@ -24050,12 +24515,12 @@ async function exec(args) {
24050
24515
  throw err2;
24051
24516
  }
24052
24517
  }
24053
- var import_node_fs9, import_node_child_process3, import_node_util, execFileAsync, resolvedBin, REDACTED_VALUE_FLAGS;
24518
+ var import_node_fs10, import_node_child_process3, import_node_util, execFileAsync, resolvedBin, REDACTED_VALUE_FLAGS;
24054
24519
  var init_bin = __esm({
24055
24520
  "../core/src/xmtp-sdk/onchainos/bin.ts"() {
24056
24521
  "use strict";
24057
24522
  init_log();
24058
- import_node_fs9 = require("node:fs");
24523
+ import_node_fs10 = require("node:fs");
24059
24524
  import_node_child_process3 = require("node:child_process");
24060
24525
  import_node_util = require("node:util");
24061
24526
  init_sentry_logger();
@@ -66763,7 +67228,7 @@ function createAsyncStreamProxy(stream) {
66763
67228
  function isHexString(value) {
66764
67229
  return typeof value === "string" && /^0x(?:[0-9a-fA-F]{2})+$/.test(value);
66765
67230
  }
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;
67231
+ 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
67232
  var init_dist4 = __esm({
66768
67233
  "../../node_modules/@xmtp/node-sdk/dist/index.js"() {
66769
67234
  init_dist2();
@@ -66772,7 +67237,7 @@ var init_dist4 = __esm({
66772
67237
  import_node_bindings2 = require("@xmtp/node-bindings");
66773
67238
  init_dist();
66774
67239
  import_types = require("node:util/types");
66775
- import_node_path12 = require("node:path");
67240
+ import_node_path13 = require("node:path");
66776
67241
  import_node_process = __toESM(require("node:process"), 1);
66777
67242
  ApiUrls = {
66778
67243
  local: "http://localhost:5556",
@@ -68018,7 +68483,7 @@ var init_dist4 = __esm({
68018
68483
  const inboxId = await getInboxIdForIdentifier(identifier, env, gatewayHost) || generateInboxId(identifier, options?.nonce);
68019
68484
  let dbPath;
68020
68485
  if (options?.dbPath === void 0) {
68021
- dbPath = (0, import_node_path12.join)(import_node_process.default.cwd(), `xmtp-${env}-${inboxId}.db3`);
68486
+ dbPath = (0, import_node_path13.join)(import_node_process.default.cwd(), `xmtp-${env}-${inboxId}.db3`);
68022
68487
  } else if (typeof options.dbPath === "function") {
68023
68488
  dbPath = options.dbPath(inboxId);
68024
68489
  } else {
@@ -82804,7 +83269,7 @@ var init_agent_status = __esm({
82804
83269
 
82805
83270
  // ../core/src/xmtp-sdk/index.ts
82806
83271
  function cachePath(dataDir, fileName) {
82807
- return (0, import_node_path13.join)(dataDir, fileName);
83272
+ return (0, import_node_path14.join)(dataDir, fileName);
82808
83273
  }
82809
83274
  function ensureCacheDir(dataDir) {
82810
83275
  ensureA2aTaskDir(dataDir);
@@ -82827,10 +83292,10 @@ function isSessionExpiredError(err2) {
82827
83292
  function loadSensitiveWordsFromCache(dataDir) {
82828
83293
  try {
82829
83294
  const path = cachePath(dataDir, "sensitive-words.json");
82830
- if (!(0, import_node_fs10.existsSync)(path)) {
83295
+ if (!(0, import_node_fs11.existsSync)(path)) {
82831
83296
  return null;
82832
83297
  }
82833
- const data = JSON.parse((0, import_node_fs10.readFileSync)(path, "utf-8"));
83298
+ const data = JSON.parse((0, import_node_fs11.readFileSync)(path, "utf-8"));
82834
83299
  if (Array.isArray(data)) {
82835
83300
  return data;
82836
83301
  }
@@ -82844,7 +83309,7 @@ function loadSensitiveWordsFromCache(dataDir) {
82844
83309
  function saveSensitiveWordsToCache(dataDir, words) {
82845
83310
  try {
82846
83311
  ensureCacheDir(dataDir);
82847
- (0, import_node_fs10.writeFileSync)(cachePath(dataDir, "sensitive-words.json"), JSON.stringify(words));
83312
+ (0, import_node_fs11.writeFileSync)(cachePath(dataDir, "sensitive-words.json"), JSON.stringify(words));
82848
83313
  } catch (err2) {
82849
83314
  logWithTimestamp(`[xmtp-sdk] failed to write sensitive-words.json:`, err2);
82850
83315
  logger.error(LogEvent.CACHE_WRITE_FAILED, err2 instanceof Error ? err2 : new Error(String(err2)), { cacheName: "sensitive-words" });
@@ -82886,10 +83351,10 @@ async function loadSensitiveWordsWith(dataDir, fetcher) {
82886
83351
  function loadSystemConfigFromCache(dataDir) {
82887
83352
  try {
82888
83353
  const path = cachePath(dataDir, "system-config.json");
82889
- if (!(0, import_node_fs10.existsSync)(path)) {
83354
+ if (!(0, import_node_fs11.existsSync)(path)) {
82890
83355
  return null;
82891
83356
  }
82892
- const data = JSON.parse((0, import_node_fs10.readFileSync)(path, "utf-8"));
83357
+ const data = JSON.parse((0, import_node_fs11.readFileSync)(path, "utf-8"));
82893
83358
  if (data && typeof data === "object" && !Array.isArray(data)) {
82894
83359
  return data;
82895
83360
  }
@@ -82903,7 +83368,7 @@ function loadSystemConfigFromCache(dataDir) {
82903
83368
  function saveSystemConfigToCache(dataDir, config) {
82904
83369
  try {
82905
83370
  ensureCacheDir(dataDir);
82906
- (0, import_node_fs10.writeFileSync)(cachePath(dataDir, "system-config.json"), JSON.stringify(config));
83371
+ (0, import_node_fs11.writeFileSync)(cachePath(dataDir, "system-config.json"), JSON.stringify(config));
82907
83372
  } catch (err2) {
82908
83373
  logWithTimestamp(`[xmtp-sdk] failed to write system-config.json:`, err2);
82909
83374
  logger.error(LogEvent.CACHE_WRITE_FAILED, err2 instanceof Error ? err2 : new Error(String(err2)), { cacheName: "system-config" });
@@ -82950,10 +83415,10 @@ function loadSyncByAddress(dataDir) {
82950
83415
  const map = /* @__PURE__ */ new Map();
82951
83416
  try {
82952
83417
  const path = cachePath(dataDir, "last-sync.json");
82953
- if (!(0, import_node_fs10.existsSync)(path)) {
83418
+ if (!(0, import_node_fs11.existsSync)(path)) {
82954
83419
  return map;
82955
83420
  }
82956
- const data = JSON.parse((0, import_node_fs10.readFileSync)(path, "utf-8"));
83421
+ const data = JSON.parse((0, import_node_fs11.readFileSync)(path, "utf-8"));
82957
83422
  const obj = data?.syncByAddress;
82958
83423
  if (obj && typeof obj === "object" && !Array.isArray(obj)) {
82959
83424
  for (const [addr, ts] of Object.entries(obj)) {
@@ -82972,9 +83437,9 @@ function saveSyncForAddress(dataDir, address, timestampMs) {
82972
83437
  try {
82973
83438
  let data = {};
82974
83439
  const path = cachePath(dataDir, "last-sync.json");
82975
- if ((0, import_node_fs10.existsSync)(path)) {
83440
+ if ((0, import_node_fs11.existsSync)(path)) {
82976
83441
  try {
82977
- const raw = JSON.parse((0, import_node_fs10.readFileSync)(path, "utf-8"));
83442
+ const raw = JSON.parse((0, import_node_fs11.readFileSync)(path, "utf-8"));
82978
83443
  if (raw && typeof raw === "object" && !Array.isArray(raw)) {
82979
83444
  data = raw;
82980
83445
  }
@@ -82985,7 +83450,7 @@ function saveSyncForAddress(dataDir, address, timestampMs) {
82985
83450
  data.syncByAddress = {};
82986
83451
  }
82987
83452
  data.syncByAddress[address] = timestampMs;
82988
- (0, import_node_fs10.writeFileSync)(path, JSON.stringify(data, null, 2));
83453
+ (0, import_node_fs11.writeFileSync)(path, JSON.stringify(data, null, 2));
82989
83454
  } catch (err2) {
82990
83455
  logWithTimestamp(
82991
83456
  `[xmtp-sdk] failed to write last-sync.json (address=${address}):`,
@@ -83162,13 +83627,13 @@ function createOfflineReplayAddressSummary(address) {
83162
83627
  durationMs: 0
83163
83628
  };
83164
83629
  }
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;
83630
+ 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
83631
  var init_xmtp_sdk = __esm({
83167
83632
  "../core/src/xmtp-sdk/index.ts"() {
83168
83633
  "use strict";
83169
83634
  init_log();
83170
- import_node_fs10 = require("node:fs");
83171
- import_node_path13 = require("node:path");
83635
+ import_node_fs11 = require("node:fs");
83636
+ import_node_path14 = require("node:path");
83172
83637
  init_dist4();
83173
83638
  init_sentry_logger();
83174
83639
  init_extract_job_id();
@@ -85182,12 +85647,12 @@ function loadSqlite3() {
85182
85647
  process.emitWarning = originalEmitWarning;
85183
85648
  }
85184
85649
  }
85185
- var import_node_fs11, import_node_path14, DatabaseSync3, InvalidXmtpMessageStore;
85650
+ var import_node_fs12, import_node_path15, DatabaseSync3, InvalidXmtpMessageStore;
85186
85651
  var init_invalid_message_store = __esm({
85187
85652
  "src/invalid-message-store.ts"() {
85188
85653
  "use strict";
85189
- import_node_fs11 = require("node:fs");
85190
- import_node_path14 = require("node:path");
85654
+ import_node_fs12 = require("node:fs");
85655
+ import_node_path15 = require("node:path");
85191
85656
  init_paths();
85192
85657
  ({ DatabaseSync: DatabaseSync3 } = loadSqlite3());
85193
85658
  InvalidXmtpMessageStore = class {
@@ -85195,8 +85660,8 @@ var init_invalid_message_store = __esm({
85195
85660
  db;
85196
85661
  constructor(homeDir) {
85197
85662
  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 });
85663
+ this.dbPath = (0, import_node_path15.join)(paths.sqliteDir, "invalid-xmtp-messages.sqlite");
85664
+ (0, import_node_fs12.mkdirSync)((0, import_node_path15.dirname)(this.dbPath), { recursive: true });
85200
85665
  this.db = new DatabaseSync3(this.dbPath);
85201
85666
  this.ensureReady();
85202
85667
  }
@@ -85431,15 +85896,27 @@ function resolveOutboundProvider(store, input) {
85431
85896
  if (input.override) {
85432
85897
  return input.override;
85433
85898
  }
85899
+ if (input.jobId && resolveOpenClawGatewayRoute(store, { jobId: input.jobId })) {
85900
+ return "openclaw";
85901
+ }
85434
85902
  try {
85435
- return resolveConfiguredAiProviderForJob({
85903
+ const configured = resolveConfiguredAiProviderForJob({
85436
85904
  store,
85437
85905
  jobId: input.jobId,
85438
85906
  env: process.env
85439
- }) ?? "codex";
85907
+ });
85908
+ if (configured) {
85909
+ return configured;
85910
+ }
85440
85911
  } catch {
85441
- return "codex";
85442
85912
  }
85913
+ if (readSyncedOpenClawGatewayConfig(store.homeDir)) {
85914
+ if (input.jobId?.trim()) {
85915
+ return store.bindJobProviderIfMissing({ jobId: input.jobId.trim(), provider: "openclaw" }).binding.provider;
85916
+ }
85917
+ return "openclaw";
85918
+ }
85919
+ return "codex";
85443
85920
  }
85444
85921
  async function notifyAgentMessageToUserAttention(input) {
85445
85922
  const ownedStore = input.store ? null : new SessionStore();
@@ -85537,6 +86014,8 @@ var init_agent_message_notice = __esm({
85537
86014
  init_session_store();
85538
86015
  init_ai_provider();
85539
86016
  init_outbound_behavior();
86017
+ init_openclaw_route();
86018
+ init_openclaw_gateway_config();
85540
86019
  DIRECTION_PREFIX = {
85541
86020
  ["outbound" /* OUTBOUND */]: "\u{1F4E4} [Sent]",
85542
86021
  ["inbound" /* INBOUND */]: "\u{1F4E5} [Received]"
@@ -85591,6 +86070,9 @@ function bindOutboundJobProviderToCurrentDefault(sessionStore, jobId) {
85591
86070
  logWithTimestamp(`[okx-agent-task] job provider bind failed from outbound-xmtp: job=${jobId}`, err2);
85592
86071
  }
85593
86072
  }
86073
+ function bindOutboundOpenClawRouteIfCurrent(sessionStore, jobId, gatewaySessionKeys) {
86074
+ bindOpenClawGatewayRouteFromEnv(sessionStore, { jobId, gatewaySessionKeys });
86075
+ }
85594
86076
  function buildTaskPayload(replyToMessageId) {
85595
86077
  return {
85596
86078
  taskMinVersion: TASK_MIN_VERSION,
@@ -86025,6 +86507,7 @@ async function handleSqliteGroupSendCommand(params) {
86025
86507
  myAgentXmtpAddress: myXmtpAddress,
86026
86508
  toAgentXmtpAddress: remote.toXmtpAddress
86027
86509
  });
86510
+ bindOutboundOpenClawRouteIfCurrent(sessionStore, command.jobId, command.gatewaySessionKeys);
86028
86511
  return { conversation: conversation2, created: created2 };
86029
86512
  }
86030
86513
  );
@@ -86351,7 +86834,7 @@ async function handleXmtpSendCommand(params) {
86351
86834
  const sessionStore2 = params.sessionStore ?? ownedStore2;
86352
86835
  try {
86353
86836
  bindOutboundJobProviderToCurrentDefault(sessionStore2, command.jobId);
86354
- resolveConfiguredAiProviderForJob({ store: sessionStore2, jobId: command.jobId });
86837
+ bindOutboundOpenClawRouteIfCurrent(sessionStore2, command.jobId, command.gatewaySessionKeys);
86355
86838
  return await handleSqliteGroupSendCommand({
86356
86839
  command,
86357
86840
  service,
@@ -86365,7 +86848,7 @@ async function handleXmtpSendCommand(params) {
86365
86848
  const sessionStore = params.sessionStore ?? ownedStore;
86366
86849
  try {
86367
86850
  bindOutboundJobProviderToCurrentDefault(sessionStore, command.jobId);
86368
- resolveConfiguredAiProviderForJob({ store: sessionStore, jobId: command.jobId });
86851
+ bindOutboundOpenClawRouteIfCurrent(sessionStore, command.jobId, command.gatewaySessionKeys);
86369
86852
  const { file, sessionAgentId } = await readFileForSend({
86370
86853
  command,
86371
86854
  store,
@@ -86457,6 +86940,7 @@ var init_xmtp_send = __esm({
86457
86940
  init_session_store();
86458
86941
  init_ai_provider();
86459
86942
  init_agent_message_notice();
86943
+ init_openclaw_route();
86460
86944
  TASK_MIN_VERSION = 1;
86461
86945
  sqliteGroupSessionPromises = /* @__PURE__ */ new Map();
86462
86946
  resolvedAgentByIdCache = /* @__PURE__ */ new Map();
@@ -86545,7 +87029,7 @@ function buildAiAdapterCommand(options) {
86545
87029
  function readCodexAddDirs(env = process.env) {
86546
87030
  const raw = env.OKX_A2A_AI_CODEX_ADD_DIRS ?? env.OKX_AGENT_TASK_CODEX_ADD_DIRS ?? "";
86547
87031
  const seen = /* @__PURE__ */ new Set();
86548
- return raw.split(import_node_path15.delimiter).map((value) => expandHomePath(value.trim())).filter(Boolean).filter((dir) => {
87032
+ return raw.split(import_node_path16.delimiter).map((value) => expandHomePath(value.trim())).filter(Boolean).filter((dir) => {
86549
87033
  if (seen.has(dir)) {
86550
87034
  return false;
86551
87035
  }
@@ -86555,10 +87039,10 @@ function readCodexAddDirs(env = process.env) {
86555
87039
  }
86556
87040
  function expandHomePath(value) {
86557
87041
  if (value === "~") {
86558
- return (0, import_node_os3.homedir)();
87042
+ return (0, import_node_os4.homedir)();
86559
87043
  }
86560
87044
  if (value.startsWith("~/")) {
86561
- return (0, import_node_path15.join)((0, import_node_os3.homedir)(), value.slice(2));
87045
+ return (0, import_node_path16.join)((0, import_node_os4.homedir)(), value.slice(2));
86562
87046
  }
86563
87047
  return value;
86564
87048
  }
@@ -86764,9 +87248,9 @@ function formatOpenClawSessionKey(sessionKey, agentId) {
86764
87248
  function buildClaudeAddDirArgs(homeDir, env) {
86765
87249
  const dirs = [
86766
87250
  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) : []
87251
+ (0, import_node_path16.join)((0, import_node_os4.homedir)(), ".agents"),
87252
+ (0, import_node_path16.join)(__dirname, ".."),
87253
+ ...env.OKX_A2A_AI_CLAUDE_ADD_DIRS ? env.OKX_A2A_AI_CLAUDE_ADD_DIRS.split(import_node_path16.delimiter).filter(Boolean) : []
86770
87254
  ];
86771
87255
  return ["--add-dir", ...[...new Set(dirs)]];
86772
87256
  }
@@ -86818,17 +87302,17 @@ function applyArgTemplate(template, options) {
86818
87302
  const homeDir = options.homeDir ?? resolveTaskPaths().homeDir;
86819
87303
  const cwd = options.cwd ?? process.cwd();
86820
87304
  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"));
87305
+ 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
87306
  });
86823
87307
  }
86824
- var import_node_child_process4, import_node_os3, import_node_path15, CLAUDE_ALLOWED_TOOLS, CLAUDE_PERMISSION_MODES, CODEX_SANDBOX_MODES, CODEX_APPROVAL_POLICIES;
87308
+ var import_node_child_process4, import_node_os4, import_node_path16, CLAUDE_ALLOWED_TOOLS, CLAUDE_PERMISSION_MODES, CODEX_SANDBOX_MODES, CODEX_APPROVAL_POLICIES;
86825
87309
  var init_ai_adapter = __esm({
86826
87310
  "src/ai-adapter.ts"() {
86827
87311
  "use strict";
86828
87312
  init_log();
86829
87313
  import_node_child_process4 = require("node:child_process");
86830
- import_node_os3 = require("node:os");
86831
- import_node_path15 = require("node:path");
87314
+ import_node_os4 = require("node:os");
87315
+ import_node_path16 = require("node:path");
86832
87316
  init_ai_command();
86833
87317
  init_paths();
86834
87318
  init_session_store();
@@ -86869,7 +87353,7 @@ function aiRunSentryExtra(input) {
86869
87353
  closeSignal: input.closeSignal ?? "",
86870
87354
  timedOut: input.timedOut === void 0 ? "" : String(input.timedOut),
86871
87355
  aiSessionId: input.aiSessionId ?? "",
86872
- aiLogFile: input.logPath ? (0, import_node_path16.basename)(input.logPath) : "",
87356
+ aiLogFile: input.logPath ? (0, import_node_path17.basename)(input.logPath) : "",
86873
87357
  commandPendingMs: input.commandPendingMs ?? "",
86874
87358
  queueWaitMs: input.queueWaitMs ?? "",
86875
87359
  cliMs: input.cliMs ?? "",
@@ -86901,7 +87385,7 @@ function aiRunToolFailureSentryExtra(failure, context) {
86901
87385
  closeSignal: context.closeSignal ?? "",
86902
87386
  timedOut: String(context.timedOut),
86903
87387
  aiSessionId: context.aiSessionId ?? "",
86904
- aiLogFile: (0, import_node_path16.basename)(context.logPath)
87388
+ aiLogFile: (0, import_node_path17.basename)(context.logPath)
86905
87389
  }).filter(([, value]) => value !== "");
86906
87390
  return entries.reduce((out, [key, value]) => {
86907
87391
  out[key] = String(value);
@@ -86924,7 +87408,7 @@ function safeProcessCwd() {
86924
87408
  }
86925
87409
  function isDirectory(path) {
86926
87410
  try {
86927
- return (0, import_node_fs12.statSync)(path).isDirectory();
87411
+ return (0, import_node_fs13.statSync)(path).isDirectory();
86928
87412
  } catch {
86929
87413
  return false;
86930
87414
  }
@@ -86969,13 +87453,13 @@ function extractProviderErrorMessage(text) {
86969
87453
  } catch {
86970
87454
  continue;
86971
87455
  }
86972
- if (!isRecord(parsed)) {
87456
+ if (!isRecord2(parsed)) {
86973
87457
  continue;
86974
87458
  }
86975
87459
  if (typeof parsed.message === "string" && parsed.message.trim()) {
86976
87460
  return parsed.message.trim();
86977
87461
  }
86978
- if (isRecord(parsed.error) && typeof parsed.error.message === "string" && parsed.error.message.trim()) {
87462
+ if (isRecord2(parsed.error) && typeof parsed.error.message === "string" && parsed.error.message.trim()) {
86979
87463
  return parsed.error.message.trim();
86980
87464
  }
86981
87465
  }
@@ -87013,7 +87497,7 @@ function parseAiToolFailureLine(provider, line, claudeToolCommands) {
87013
87497
  return null;
87014
87498
  }
87015
87499
  function parseCodexToolFailure(event, rawEvent) {
87016
- if (!isRecord(event) || event.type !== "item.completed" || !isRecord(event.item)) {
87500
+ if (!isRecord2(event) || event.type !== "item.completed" || !isRecord2(event.item)) {
87017
87501
  return null;
87018
87502
  }
87019
87503
  const item = event.item;
@@ -87080,7 +87564,7 @@ function extractCodexStructuredToolFailure(text) {
87080
87564
  } catch {
87081
87565
  return null;
87082
87566
  }
87083
- if (!isRecord(parsed) || !isRecord(parsed.toolFailure)) {
87567
+ if (!isRecord2(parsed) || !isRecord2(parsed.toolFailure)) {
87084
87568
  return null;
87085
87569
  }
87086
87570
  return normalizeCodexStructuredToolFailure(parsed.toolFailure, text);
@@ -87124,7 +87608,7 @@ function extractCodexToolFailureMarker(text) {
87124
87608
  } catch {
87125
87609
  return null;
87126
87610
  }
87127
- if (!isRecord(parsed) || parsed.errorType !== "permission_denied") {
87611
+ if (!isRecord2(parsed) || parsed.errorType !== "permission_denied") {
87128
87612
  return null;
87129
87613
  }
87130
87614
  const tool = typeof parsed.tool === "string" && parsed.tool.trim() ? parsed.tool.trim() : "command_execution";
@@ -87213,11 +87697,11 @@ function extractDeniedFilesystemPath(text) {
87213
87697
  }
87214
87698
  function getPreferredCodexWritableRoot(target) {
87215
87699
  const expanded = expandHomePath2(target);
87216
- const home = (0, import_node_os4.homedir)();
87700
+ const home = (0, import_node_os5.homedir)();
87217
87701
  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")
87702
+ (0, import_node_path17.join)(home, ".onchainos", "task"),
87703
+ (0, import_node_path17.join)(home, ".onchainos", "deliverables"),
87704
+ (0, import_node_path17.join)(home, ".okx-agent-task")
87221
87705
  ];
87222
87706
  for (const root of appRoots) {
87223
87707
  if (expanded === root || expanded.startsWith(`${root}/`)) {
@@ -87232,25 +87716,25 @@ function inferAppOwnedCodexWritableRoot(failure) {
87232
87716
  return void 0;
87233
87717
  }
87234
87718
  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");
87719
+ return (0, import_node_path17.join)((0, import_node_os5.homedir)(), ".onchainos", "task");
87236
87720
  }
87237
87721
  return void 0;
87238
87722
  }
87239
87723
  function expandHomePath2(value) {
87240
87724
  if (value === "~") {
87241
- return (0, import_node_os4.homedir)();
87725
+ return (0, import_node_os5.homedir)();
87242
87726
  }
87243
87727
  if (value.startsWith("~/")) {
87244
- return (0, import_node_path16.join)((0, import_node_os4.homedir)(), value.slice(2));
87728
+ return (0, import_node_path17.join)((0, import_node_os5.homedir)(), value.slice(2));
87245
87729
  }
87246
87730
  return value;
87247
87731
  }
87248
87732
  function parseClaudeToolFailure(event, rawEvent, claudeToolCommands) {
87249
- if (!isRecord(event)) {
87733
+ if (!isRecord2(event)) {
87250
87734
  return null;
87251
87735
  }
87252
87736
  rememberClaudeToolCommands(event, claudeToolCommands);
87253
- const toolUseResult = isRecord(event.tool_use_result) ? event.tool_use_result : null;
87737
+ const toolUseResult = isRecord2(event.tool_use_result) ? event.tool_use_result : null;
87254
87738
  const toolResult = findClaudeToolResult(event);
87255
87739
  if (!toolUseResult && !toolResult) {
87256
87740
  return null;
@@ -87277,7 +87761,7 @@ function parseClaudeToolFailure(event, rawEvent, claudeToolCommands) {
87277
87761
  });
87278
87762
  }
87279
87763
  function rememberClaudeToolCommands(event, commands) {
87280
- if (!isRecord(event.message)) {
87764
+ if (!isRecord2(event.message)) {
87281
87765
  return;
87282
87766
  }
87283
87767
  const content3 = event.message.content;
@@ -87285,17 +87769,17 @@ function rememberClaudeToolCommands(event, commands) {
87285
87769
  return;
87286
87770
  }
87287
87771
  for (const part of content3) {
87288
- if (!isRecord(part) || part.type !== "tool_use" || typeof part.id !== "string") {
87772
+ if (!isRecord2(part) || part.type !== "tool_use" || typeof part.id !== "string") {
87289
87773
  continue;
87290
87774
  }
87291
- if (part.name !== "Bash" || !isRecord(part.input) || typeof part.input.command !== "string") {
87775
+ if (part.name !== "Bash" || !isRecord2(part.input) || typeof part.input.command !== "string") {
87292
87776
  continue;
87293
87777
  }
87294
87778
  commands.set(part.id, part.input.command);
87295
87779
  }
87296
87780
  }
87297
87781
  function findClaudeToolResult(event) {
87298
- if (!isRecord(event.message)) {
87782
+ if (!isRecord2(event.message)) {
87299
87783
  return null;
87300
87784
  }
87301
87785
  const content3 = event.message.content;
@@ -87303,7 +87787,7 @@ function findClaudeToolResult(event) {
87303
87787
  return null;
87304
87788
  }
87305
87789
  for (const part of content3) {
87306
- if (!isRecord(part) || part.type !== "tool_result") {
87790
+ if (!isRecord2(part) || part.type !== "tool_result") {
87307
87791
  continue;
87308
87792
  }
87309
87793
  return {
@@ -87322,7 +87806,7 @@ function extractExplicitExitCode(text) {
87322
87806
  const value = Number(match[1]);
87323
87807
  return Number.isFinite(value) ? value : null;
87324
87808
  }
87325
- function isRecord(value) {
87809
+ function isRecord2(value) {
87326
87810
  return typeof value === "object" && value !== null;
87327
87811
  }
87328
87812
  function appendOutput(current, chunk, max = 4e3) {
@@ -87493,7 +87977,7 @@ function parseSessionKeyDetails(sessionKey) {
87493
87977
  kind: sessionKey || "unknown"
87494
87978
  };
87495
87979
  }
87496
- function inferJobIdFromSessionKey(sessionKey) {
87980
+ function inferJobIdFromSessionKey2(sessionKey) {
87497
87981
  const jobPrefixMatch = /^job:([^:]+):/.exec(sessionKey);
87498
87982
  if (jobPrefixMatch?.[1]) {
87499
87983
  return normalizeOptionalText(safeDecodeURIComponent(jobPrefixMatch[1]));
@@ -87713,7 +88197,7 @@ function extractCodexAgentMessagePermissionText(output4) {
87713
88197
  } catch {
87714
88198
  continue;
87715
88199
  }
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") {
88200
+ 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
88201
  return parsed.item.text;
87718
88202
  }
87719
88203
  }
@@ -88169,17 +88653,17 @@ function shortenJobId2(jobId) {
88169
88653
  }
88170
88654
  return `${jobId.slice(0, 6)}\u2026${jobId.slice(-4)}`;
88171
88655
  }
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;
88656
+ 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
88657
  var init_ai_runner = __esm({
88174
88658
  "src/ai-runner.ts"() {
88175
88659
  "use strict";
88176
88660
  init_log();
88177
88661
  import_node_crypto8 = require("node:crypto");
88178
- import_node_fs12 = require("node:fs");
88662
+ import_node_fs13 = require("node:fs");
88179
88663
  import_promises5 = require("node:fs/promises");
88180
88664
  import_node_child_process5 = require("node:child_process");
88181
- import_node_os4 = require("node:os");
88182
- import_node_path16 = require("node:path");
88665
+ import_node_os5 = require("node:os");
88666
+ import_node_path17 = require("node:path");
88183
88667
  init_ai_command();
88184
88668
  init_paths();
88185
88669
  init_file_store();
@@ -88279,7 +88763,7 @@ var init_ai_runner = __esm({
88279
88763
  if (sessionJobId) {
88280
88764
  return sessionJobId;
88281
88765
  }
88282
- return inferJobIdFromSessionKey(request.sessionKey);
88766
+ return inferJobIdFromSessionKey2(request.sessionKey);
88283
88767
  }
88284
88768
  buildRunQueueKey(request) {
88285
88769
  if (request.source === "job-dispatch") {
@@ -88306,7 +88790,7 @@ var init_ai_runner = __esm({
88306
88790
  ensureTaskDir(this.logsDir);
88307
88791
  const lifecycleLogsEnabled = isAiLifecycleLoggingEnabled();
88308
88792
  const logPath = lifecycleLogsEnabled ? this.buildRunLogPath(request) : "";
88309
- const log = lifecycleLogsEnabled ? (0, import_node_fs12.createWriteStream)(logPath, { flags: "a" }) : null;
88793
+ const log = lifecycleLogsEnabled ? (0, import_node_fs13.createWriteStream)(logPath, { flags: "a" }) : null;
88310
88794
  let existing = null;
88311
88795
  let storeReadStartedAt;
88312
88796
  let storeReadEndedAt;
@@ -88688,10 +89172,10 @@ var init_ai_runner = __esm({
88688
89172
  const safeMessageId = encodeURIComponent(request.messageId);
88689
89173
  if (request.source === "job-dispatch") {
88690
89174
  const safeJobId = encodeURIComponent(request.jobId ?? "unknown");
88691
- return (0, import_node_path16.join)(this.logsDir, `ai-${safeJobId}-${safeMessageId}.log`);
89175
+ return (0, import_node_path17.join)(this.logsDir, `ai-${safeJobId}-${safeMessageId}.log`);
88692
89176
  }
88693
89177
  const safeSessionKey = encodeURIComponent(request.sessionKey);
88694
- return (0, import_node_path16.join)(this.logsDir, `ai-session-${safeSessionKey}-${safeMessageId}.log`);
89178
+ return (0, import_node_path17.join)(this.logsDir, `ai-session-${safeSessionKey}-${safeMessageId}.log`);
88695
89179
  }
88696
89180
  readRunAiSessionId(provider, request, file, sessionMeta) {
88697
89181
  if (request.source === "job-dispatch" && request.jobId) {
@@ -88845,7 +89329,7 @@ var init_ai_runner = __esm({
88845
89329
  process.env.OKX_AGENT_TASK_AI_CWD,
88846
89330
  this.sessionStore.getSetting("ai_working_dir"),
88847
89331
  safeProcessCwd(),
88848
- (0, import_node_os4.homedir)(),
89332
+ (0, import_node_os5.homedir)(),
88849
89333
  this.homeDir
88850
89334
  ];
88851
89335
  return candidates.find((candidate) => !!candidate && isDirectory(candidate)) ?? this.homeDir;
@@ -89002,7 +89486,7 @@ var init_ai_runner = __esm({
89002
89486
  async appendLlmLog(entry) {
89003
89487
  try {
89004
89488
  ensureTaskDir(this.logsDir);
89005
- await (0, import_promises5.appendFile)((0, import_node_path16.join)(this.logsDir, "llm.log"), formatLlmLogEntry(entry), "utf8");
89489
+ await (0, import_promises5.appendFile)((0, import_node_path17.join)(this.logsDir, "llm.log"), formatLlmLogEntry(entry), "utf8");
89006
89490
  } catch (err2) {
89007
89491
  errorWithTimestamp("[okx-agent-task] failed to append llm.log:", err2);
89008
89492
  }
@@ -91133,12 +91617,12 @@ async function runListenerWithLock(options, paths) {
91133
91617
  }));
91134
91618
  }
91135
91619
  });
91136
- service.setPluginVersion("0.0.15");
91620
+ service.setPluginVersion("0.0.16-beta-d0ec14bc63-260623103149");
91137
91621
  await service.init();
91138
91622
  const pluginVersionStatus = service.pluginVersionStatus;
91139
91623
  if (pluginVersionStatus.unavailable) {
91140
91624
  throw new Error(
91141
- `@okxweb3/a2a-node v${"0.0.15"} is below the required minimum v${pluginVersionStatus.minVersion}`
91625
+ `@okxweb3/a2a-node v${"0.0.16-beta-d0ec14bc63-260623103149"} is below the required minimum v${pluginVersionStatus.minVersion}`
91142
91626
  );
91143
91627
  }
91144
91628
  const systemConfig = service.getSystemConfig();
@@ -91156,7 +91640,7 @@ async function runListenerWithLock(options, paths) {
91156
91640
  onchainosAgentId: "*",
91157
91641
  reason: "system-config missing sentryDsn",
91158
91642
  pluginId: "@okxweb3/a2a-node",
91159
- pluginVersion: "0.0.15"
91643
+ pluginVersion: "0.0.16-beta-d0ec14bc63-260623103149"
91160
91644
  });
91161
91645
  }
91162
91646
  logWithTimestamp(
@@ -91350,9 +91834,9 @@ var init_listener = __esm({
91350
91834
 
91351
91835
  // ../core/src/file-upload-safety.ts
91352
91836
  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);
91837
+ const expanded = (0, import_node_path18.resolve)(expandHome(filePath));
91838
+ const target = (0, import_node_fs14.realpathSync)(expanded);
91839
+ const targetName = (0, import_node_path18.basename)(target);
91356
91840
  if (targetName === ".env" || targetName.startsWith(".env.")) {
91357
91841
  return ".env";
91358
91842
  }
@@ -91360,18 +91844,18 @@ function getUnsafeFileUploadReason(filePath, sensitiveUploadReg = []) {
91360
91844
  if (configuredRule) {
91361
91845
  return `SENSITIVE_UPLOAD_REG:${configuredRule}`;
91362
91846
  }
91363
- const home = safeRealpath((0, import_node_os5.homedir)());
91847
+ const home = safeRealpath((0, import_node_os6.homedir)());
91364
91848
  if (!home) {
91365
91849
  return null;
91366
91850
  }
91367
91851
  for (const dir of SENSITIVE_HOME_DIRS) {
91368
- const sensitiveDir = safeRealpath((0, import_node_path17.join)(home, dir));
91852
+ const sensitiveDir = safeRealpath((0, import_node_path18.join)(home, dir));
91369
91853
  if (sensitiveDir && isPathInside(target, sensitiveDir)) {
91370
91854
  return `~/${dir}`;
91371
91855
  }
91372
91856
  }
91373
91857
  for (const file of SENSITIVE_HOME_FILES) {
91374
- const sensitiveFile = safeRealpath((0, import_node_path17.join)(home, file));
91858
+ const sensitiveFile = safeRealpath((0, import_node_path18.join)(home, file));
91375
91859
  if (sensitiveFile && target === sensitiveFile) {
91376
91860
  return `~/${file}`;
91377
91861
  }
@@ -91397,29 +91881,29 @@ function matchSensitiveUploadReg(paths, patterns) {
91397
91881
  }
91398
91882
  function expandHome(filePath) {
91399
91883
  if (filePath === "~") {
91400
- return (0, import_node_os5.homedir)();
91884
+ return (0, import_node_os6.homedir)();
91401
91885
  }
91402
- if (filePath.startsWith(`~${import_node_path17.sep}`)) {
91403
- return (0, import_node_path17.join)((0, import_node_os5.homedir)(), filePath.slice(2));
91886
+ if (filePath.startsWith(`~${import_node_path18.sep}`)) {
91887
+ return (0, import_node_path18.join)((0, import_node_os6.homedir)(), filePath.slice(2));
91404
91888
  }
91405
91889
  return filePath;
91406
91890
  }
91407
91891
  function safeRealpath(path) {
91408
- if (!(0, import_node_fs13.existsSync)(path)) {
91892
+ if (!(0, import_node_fs14.existsSync)(path)) {
91409
91893
  return null;
91410
91894
  }
91411
- return (0, import_node_fs13.realpathSync)(path);
91895
+ return (0, import_node_fs14.realpathSync)(path);
91412
91896
  }
91413
91897
  function isPathInside(target, dir) {
91414
- return target === dir || target.startsWith(`${dir}${import_node_path17.sep}`);
91898
+ return target === dir || target.startsWith(`${dir}${import_node_path18.sep}`);
91415
91899
  }
91416
- var import_node_fs13, import_node_os5, import_node_path17, SENSITIVE_HOME_DIRS, SENSITIVE_HOME_FILES, UNSAFE_FILE_UPLOAD_MESSAGE;
91900
+ var import_node_fs14, import_node_os6, import_node_path18, SENSITIVE_HOME_DIRS, SENSITIVE_HOME_FILES, UNSAFE_FILE_UPLOAD_MESSAGE;
91417
91901
  var init_file_upload_safety = __esm({
91418
91902
  "../core/src/file-upload-safety.ts"() {
91419
91903
  "use strict";
91420
- import_node_fs13 = require("node:fs");
91421
- import_node_os5 = require("node:os");
91422
- import_node_path17 = require("node:path");
91904
+ import_node_fs14 = require("node:fs");
91905
+ import_node_os6 = require("node:os");
91906
+ import_node_path18 = require("node:path");
91423
91907
  SENSITIVE_HOME_DIRS = [
91424
91908
  ".ssh",
91425
91909
  ".gnupg",
@@ -91427,7 +91911,7 @@ var init_file_upload_safety = __esm({
91427
91911
  ".azure",
91428
91912
  ".kube",
91429
91913
  ".docker",
91430
- (0, import_node_path17.join)(".config", "gcloud")
91914
+ (0, import_node_path18.join)(".config", "gcloud")
91431
91915
  ];
91432
91916
  SENSITIVE_HOME_FILES = [
91433
91917
  ".npmrc",
@@ -91489,7 +91973,7 @@ function hasHelpFlag(args) {
91489
91973
  return args.some((arg) => arg === "-h" || arg === "--help" || arg === "help");
91490
91974
  }
91491
91975
  async function uploadFile(params) {
91492
- const filename = params.filename || (0, import_node_path18.basename)(params.filePath);
91976
+ const filename = params.filename || (0, import_node_path19.basename)(params.filePath);
91493
91977
  const mimeType = params.mimeType || "application/octet-stream";
91494
91978
  const uploadConfig = readUploadSystemConfig();
91495
91979
  const unsafeReason = getUnsafeFileUploadReason(params.filePath, uploadConfig.sensitiveUploadReg);
@@ -91505,16 +91989,16 @@ async function uploadFile(params) {
91505
91989
  return;
91506
91990
  }
91507
91991
  const maxFileSizeBytes = uploadConfig.maxFileSizeBytes;
91508
- const fileSize = (0, import_node_fs14.statSync)(params.filePath).size;
91992
+ const fileSize = (0, import_node_fs15.statSync)(params.filePath).size;
91509
91993
  if (fileSize > maxFileSizeBytes) {
91510
91994
  throw new Error(formatFileTooLargeMessage(maxFileSizeBytes));
91511
91995
  }
91512
- const data = (0, import_node_fs14.readFileSync)(params.filePath);
91996
+ const data = (0, import_node_fs15.readFileSync)(params.filePath);
91513
91997
  const attachment = { filename, mimeType, data: new Uint8Array(data) };
91514
91998
  const encrypted = await RemoteAttachmentCodec.encodeEncrypted(attachment, new AttachmentCodec());
91515
91999
  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);
92000
+ const encryptedPath = (0, import_node_path19.resolve)(FILE_WORK_DIR, `${(0, import_node_crypto11.randomUUID)()}.enc`);
92001
+ (0, import_node_fs15.writeFileSync)(encryptedPath, encrypted.payload);
91518
92002
  try {
91519
92003
  const stdout = runOnchainos([
91520
92004
  "agent",
@@ -91550,14 +92034,14 @@ async function uploadFile(params) {
91550
92034
  }, null, 2));
91551
92035
  } finally {
91552
92036
  try {
91553
- (0, import_node_fs14.unlinkSync)(encryptedPath);
92037
+ (0, import_node_fs15.unlinkSync)(encryptedPath);
91554
92038
  } catch {
91555
92039
  }
91556
92040
  }
91557
92041
  }
91558
92042
  async function downloadFile(params) {
91559
92043
  ensureFileDirs();
91560
- const encryptedPath = (0, import_node_path18.resolve)(FILE_WORK_DIR, `${(0, import_node_crypto11.randomUUID)()}.enc`);
92044
+ const encryptedPath = (0, import_node_path19.resolve)(FILE_WORK_DIR, `${(0, import_node_crypto11.randomUUID)()}.enc`);
91561
92045
  try {
91562
92046
  const stdout = runOnchainos([
91563
92047
  "agent",
@@ -91581,7 +92065,7 @@ async function downloadFile(params) {
91581
92065
  }));
91582
92066
  throw new Error(`file download failed: ${stdout}`);
91583
92067
  }
91584
- const payload = new Uint8Array((0, import_node_fs14.readFileSync)(encryptedPath));
92068
+ const payload = new Uint8Array((0, import_node_fs15.readFileSync)(encryptedPath));
91585
92069
  const digestBytes = new Uint8Array(await import_node_crypto11.webcrypto.subtle.digest("SHA-256", payload));
91586
92070
  const actualDigest = Array.from(digestBytes).map((byte) => byte.toString(16).padStart(2, "0")).join("");
91587
92071
  if (actualDigest !== params.digest) {
@@ -91593,12 +92077,12 @@ async function downloadFile(params) {
91593
92077
  const outputFilename = params.filename || attachment.filename || `${(0, import_node_crypto11.randomUUID)()}.bin`;
91594
92078
  const outputDir = DOWNLOADS_DIR;
91595
92079
  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);
92080
+ const outputPath = (0, import_node_path19.resolve)(outputDir, (0, import_node_path19.basename)(outputFilename));
92081
+ (0, import_node_fs15.writeFileSync)(outputPath, attachment.data);
91598
92082
  console.log(outputPath);
91599
92083
  } finally {
91600
92084
  try {
91601
- (0, import_node_fs14.unlinkSync)(encryptedPath);
92085
+ (0, import_node_fs15.unlinkSync)(encryptedPath);
91602
92086
  } catch {
91603
92087
  }
91604
92088
  }
@@ -91694,7 +92178,7 @@ function readUploadSystemConfig() {
91694
92178
  const res = parseCliJson2(stdout, "system-config");
91695
92179
  if (res.data && typeof res.data === "object") {
91696
92180
  ensureA2aTaskDir(OKX_A2A_PATHS.xmtpDir);
91697
- (0, import_node_fs14.writeFileSync)(SYSTEM_CONFIG_PATH, JSON.stringify(res.data));
92181
+ (0, import_node_fs15.writeFileSync)(SYSTEM_CONFIG_PATH, JSON.stringify(res.data));
91698
92182
  }
91699
92183
  return parseUploadSystemConfig(res.data ?? {});
91700
92184
  } catch {
@@ -91717,10 +92201,10 @@ function fileCliSentryExtra(operation, reason, extra = {}) {
91717
92201
  }
91718
92202
  function readSystemConfigFromCache() {
91719
92203
  try {
91720
- if (!(0, import_node_fs14.existsSync)(SYSTEM_CONFIG_PATH)) {
92204
+ if (!(0, import_node_fs15.existsSync)(SYSTEM_CONFIG_PATH)) {
91721
92205
  return null;
91722
92206
  }
91723
- return JSON.parse((0, import_node_fs14.readFileSync)(SYSTEM_CONFIG_PATH, "utf8"));
92207
+ return JSON.parse((0, import_node_fs15.readFileSync)(SYSTEM_CONFIG_PATH, "utf8"));
91724
92208
  } catch {
91725
92209
  return null;
91726
92210
  }
@@ -91754,14 +92238,14 @@ function readRequiredOption(args, name2) {
91754
92238
  }
91755
92239
  return value;
91756
92240
  }
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;
92241
+ 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
92242
  var init_file_cli = __esm({
91759
92243
  "src/file-cli.ts"() {
91760
92244
  "use strict";
91761
92245
  import_node_child_process6 = require("node:child_process");
91762
92246
  import_node_crypto11 = require("node:crypto");
91763
- import_node_fs14 = require("node:fs");
91764
- import_node_path18 = require("node:path");
92247
+ import_node_fs15 = require("node:fs");
92248
+ import_node_path19 = require("node:path");
91765
92249
  init_dist6();
91766
92250
  import_proto4 = __toESM(require_node3());
91767
92251
  init_a2a_paths();
@@ -91772,7 +92256,7 @@ var init_file_cli = __esm({
91772
92256
  OKX_A2A_HOME_DIR = OKX_A2A_PATHS.homeDir;
91773
92257
  FILE_WORK_DIR = process.env.OKX_A2A_FILE_WORK_DIR || OKX_A2A_PATHS.filesDir;
91774
92258
  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");
92259
+ SYSTEM_CONFIG_PATH = (0, import_node_path19.resolve)(OKX_A2A_PATHS.xmtpDir, "system-config.json");
91776
92260
  }
91777
92261
  });
91778
92262
 
@@ -92268,7 +92752,7 @@ function readJobId(parsed) {
92268
92752
  return envJobId;
92269
92753
  }
92270
92754
  const sessionKey = readCurrentSessionKeyFromEnv();
92271
- return sessionKey ? inferJobIdFromSessionKey2(sessionKey) : null;
92755
+ return sessionKey ? inferJobIdFromSessionKey3(sessionKey) : null;
92272
92756
  }
92273
92757
  function assertNoUserSessionKey(parsed, subcommand) {
92274
92758
  if (parsed.options.has("session-key")) {
@@ -92428,7 +92912,7 @@ function isHermesRouteBindingDebugEnabled() {
92428
92912
  const value = process.env.OKX_A2A_DEBUG_HERMES_ROUTE_BINDING ?? "";
92429
92913
  return value === "1" || value.toLowerCase() === "true";
92430
92914
  }
92431
- function inferJobIdFromSessionKey2(sessionKey) {
92915
+ function inferJobIdFromSessionKey3(sessionKey) {
92432
92916
  const jobPrefix = /^job:([^:]+):/.exec(sessionKey);
92433
92917
  if (jobPrefix?.[1]) {
92434
92918
  return normalizeOptionalText2(safeDecodeURIComponent2(jobPrefix[1]));
@@ -92518,6 +93002,7 @@ async function handleSessionCommand(args) {
92518
93002
  const provider = resolveSessionLifecycleProvider(store, input.jobId);
92519
93003
  if (provider === "openclaw") {
92520
93004
  usedOpenClawGateway = true;
93005
+ bindOpenClawGatewayRouteFromEnv(store, { jobId: input.jobId });
92521
93006
  await createOutboundBehavior(provider, { store }).createSession({
92522
93007
  sessionKey: input.sessionKey,
92523
93008
  jobId: input.jobId,
@@ -92591,7 +93076,7 @@ async function handleSessionCommand(args) {
92591
93076
  const exactExisting = exactSessionKey ? store.getSession(exactSessionKey) : null;
92592
93077
  const provider = resolveSessionDeleteProvider(
92593
93078
  store,
92594
- exactExisting?.jobId ?? (exactSessionKey ? inferJobIdFromSessionKey3(exactSessionKey) : jobId)
93079
+ exactExisting?.jobId ?? (exactSessionKey ? inferJobIdFromSessionKey4(exactSessionKey) : jobId)
92595
93080
  );
92596
93081
  if (provider === "openclaw") {
92597
93082
  usedOpenClawGateway = true;
@@ -93272,7 +93757,7 @@ function resolveSendSessionTargets(parsed, store) {
93272
93757
  if (sessionKey) {
93273
93758
  return [{
93274
93759
  sessionKey,
93275
- jobId: parsed.options.get("job-id") ?? inferJobIdFromSessionKey3(sessionKey),
93760
+ jobId: parsed.options.get("job-id") ?? inferJobIdFromSessionKey4(sessionKey),
93276
93761
  agentId: parsed.options.get("agent-id") ?? parsed.options.get("my-agent-id") ?? null,
93277
93762
  toAgentId: null
93278
93763
  }];
@@ -93353,7 +93838,7 @@ function parseModernSessionKey(sessionKey) {
93353
93838
  toAgentId: decodeURIComponent(parts[5])
93354
93839
  };
93355
93840
  }
93356
- function inferJobIdFromSessionKey3(sessionKey) {
93841
+ function inferJobIdFromSessionKey4(sessionKey) {
93357
93842
  const modern = parseModernSessionKey(sessionKey);
93358
93843
  if (modern?.jobId) {
93359
93844
  return modern.jobId;
@@ -93441,6 +93926,7 @@ var init_session_cli = __esm({
93441
93926
  init_ai_dispatch_queue();
93442
93927
  init_ai_provider();
93443
93928
  init_outbound_behavior();
93929
+ init_openclaw_route();
93444
93930
  init_openclaw_gateway();
93445
93931
  init_sentry_logger();
93446
93932
  init_openclaw_gateway_config();
@@ -93912,7 +94398,7 @@ function detectSetupTarget() {
93912
94398
  }
93913
94399
  const gatewayProviders = [
93914
94400
  ...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"] : []
94401
+ ...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
94402
  ];
93917
94403
  if (gatewayProviders.length === 1) {
93918
94404
  return gatewayProviders[0];
@@ -93969,7 +94455,7 @@ async function getCurrentNodeCliVersion() {
93969
94455
  return await getGlobalNpmPackageVersion(UPDATE_PACKAGES.node) ?? getBundledNodeCliVersion();
93970
94456
  }
93971
94457
  function getBundledNodeCliVersion() {
93972
- return true ? "0.0.15" : null;
94458
+ return true ? "0.0.16-beta-d0ec14bc63-260623103149" : null;
93973
94459
  }
93974
94460
  function readConfiguredAiProvider() {
93975
94461
  const explicit = process.env.OKX_AGENT_TASK_AI_CLI ?? process.env.OKX_A2A_AI_PROVIDER;
@@ -94039,17 +94525,17 @@ async function updateHermes(release, options) {
94039
94525
  const label = options.label ?? "update";
94040
94526
  assertNotRunningInsideGateway("hermes");
94041
94527
  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-`));
94528
+ const workDir = await (0, import_promises6.mkdtemp)((0, import_node_path20.join)((0, import_node_os7.tmpdir)(), `okx-a2a-${label}-hermes-`));
94043
94529
  try {
94044
94530
  console.log(`[${label}] downloading ${spec}`);
94045
94531
  const npmTarball = await npmPack(spec, workDir);
94046
- const npmPackageDir = (0, import_node_path19.join)(workDir, "npm-package");
94532
+ const npmPackageDir = (0, import_node_path20.join)(workDir, "npm-package");
94047
94533
  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");
94534
+ const pluginTarball = await findHermesPluginTarball((0, import_node_path20.join)(npmPackageDir, "package", "dist"));
94535
+ const pluginDir = (0, import_node_path20.join)(workDir, "plugin");
94050
94536
  await runCommand("tar", ["-xzf", pluginTarball, "-C", pluginDir], { ensureDir: pluginDir });
94051
94537
  const unpackedPluginDir = await findFirstDirectory(pluginDir);
94052
- const installer = (0, import_node_path19.join)(unpackedPluginDir, "scripts", "install-or-upgrade.sh");
94538
+ const installer = (0, import_node_path20.join)(unpackedPluginDir, "scripts", "install-or-upgrade.sh");
94053
94539
  console.log(`[${label}] running ${installer}`);
94054
94540
  await runCommand("bash", [installer, ...options.restart ? ["--restart"] : []], { cwd: unpackedPluginDir });
94055
94541
  await normalizeHermesOkxA2aPluginConfig();
@@ -94085,7 +94571,7 @@ async function ensureHermesOkxA2aPluginConfig(configFile = resolveHermesConfigPa
94085
94571
  content3 = await (0, import_promises6.readFile)(configFile, "utf8");
94086
94572
  } catch (error) {
94087
94573
  if (isNodeError(error) && error.code === "ENOENT") {
94088
- await (0, import_promises6.mkdir)((0, import_node_path19.resolve)(configFile, ".."), { recursive: true });
94574
+ await (0, import_promises6.mkdir)((0, import_node_path20.resolve)(configFile, ".."), { recursive: true });
94089
94575
  await (0, import_promises6.writeFile)(configFile, "plugins:\n enabled:\n - okx-a2a\n");
94090
94576
  console.log(`[update] added Hermes plugins.enabled okx-a2a entry in ${configFile}`);
94091
94577
  return true;
@@ -94245,7 +94731,7 @@ function addHermesOkxA2aEnabled(content3) {
94245
94731
  return `${lines.join("\n")}${trailingNewline ? "\n" : ""}`;
94246
94732
  }
94247
94733
  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");
94734
+ return (0, import_node_path20.join)(process.env.HERMES_HOME ?? (0, import_node_path20.join)((0, import_node_os7.homedir)(), ".hermes"), "config.yaml");
94249
94735
  }
94250
94736
  function lineIndent(line) {
94251
94737
  const match = line.match(/^\s*/);
@@ -94318,7 +94804,7 @@ async function isGatewayPluginInstalled(target) {
94318
94804
  if (target === "openclaw") {
94319
94805
  return (await getInstalledOpenClawPluginInfo()).installed;
94320
94806
  }
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"))) {
94807
+ 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
94808
  return true;
94323
94809
  }
94324
94810
  return await isGlobalNpmPackageInstalled(UPDATE_PACKAGES.hermes);
@@ -94412,7 +94898,7 @@ function parsePackageVersionFromText(output4) {
94412
94898
  return output4.match(/@okxweb3\/a2a-openclaw@([0-9A-Za-z.+-]+)/)?.[1] ?? null;
94413
94899
  }
94414
94900
  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");
94901
+ 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
94902
  try {
94417
94903
  const content3 = await (0, import_promises6.readFile)(pluginYaml, "utf8");
94418
94904
  return parsePluginYamlVersion(content3);
@@ -94465,7 +94951,7 @@ async function npmPack(spec, destination) {
94465
94951
  if (!tarballName) {
94466
94952
  throw new Error(`Unable to detect npm pack tarball from output: ${output4.trim()}`);
94467
94953
  }
94468
- return (0, import_node_path19.resolve)(destination, (0, import_node_path19.basename)(tarballName));
94954
+ return (0, import_node_path20.resolve)(destination, (0, import_node_path20.basename)(tarballName));
94469
94955
  }
94470
94956
  async function findHermesPluginTarball(distDir) {
94471
94957
  const entries = await (0, import_promises6.readdir)(distDir);
@@ -94473,7 +94959,7 @@ async function findHermesPluginTarball(distDir) {
94473
94959
  if (!tarball) {
94474
94960
  throw new Error(`Hermes npm package did not contain dist/okx-a2a-hermes-plugin-*.tar.gz`);
94475
94961
  }
94476
- return (0, import_node_path19.join)(distDir, tarball);
94962
+ return (0, import_node_path20.join)(distDir, tarball);
94477
94963
  }
94478
94964
  async function findFirstDirectory(parent) {
94479
94965
  const entries = await (0, import_promises6.readdir)(parent, { withFileTypes: true });
@@ -94481,7 +94967,7 @@ async function findFirstDirectory(parent) {
94481
94967
  if (!dir) {
94482
94968
  throw new Error(`No unpacked plugin directory found under ${parent}`);
94483
94969
  }
94484
- return (0, import_node_path19.join)(parent, dir.name);
94970
+ return (0, import_node_path20.join)(parent, dir.name);
94485
94971
  }
94486
94972
  function readOption2(args, name2) {
94487
94973
  const index2 = args.indexOf(name2);
@@ -94588,15 +95074,15 @@ async function runCommandCaptureOptional(command, args) {
94588
95074
  });
94589
95075
  });
94590
95076
  }
94591
- var import_node_child_process7, import_node_fs15, import_promises6, import_node_os6, import_node_path19, UPDATE_PACKAGES, OPENCLAW_UNSAFE_INSTALL_FLAG, redirectCommandStdoutToStderr;
95077
+ var import_node_child_process7, import_node_fs16, import_promises6, import_node_os7, import_node_path20, UPDATE_PACKAGES, OPENCLAW_UNSAFE_INSTALL_FLAG, redirectCommandStdoutToStderr;
94592
95078
  var init_update_cli = __esm({
94593
95079
  "src/update-cli.ts"() {
94594
95080
  "use strict";
94595
95081
  import_node_child_process7 = require("node:child_process");
94596
- import_node_fs15 = require("node:fs");
95082
+ import_node_fs16 = require("node:fs");
94597
95083
  import_promises6 = require("node:fs/promises");
94598
- import_node_os6 = require("node:os");
94599
- import_node_path19 = require("node:path");
95084
+ import_node_os7 = require("node:os");
95085
+ import_node_path20 = require("node:path");
94600
95086
  init_ai_provider();
94601
95087
  init_ai_command();
94602
95088
  init_session_store();
@@ -94612,21 +95098,23 @@ var init_update_cli = __esm({
94612
95098
 
94613
95099
  // src/cli.ts
94614
95100
  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");
95101
+ var import_node_fs17 = require("node:fs");
95102
+ var import_node_os8 = require("node:os");
95103
+ var import_node_path21 = require("node:path");
94618
95104
  init_daemon();
94619
95105
  init_command_store();
94620
95106
  init_file_store();
94621
95107
  init_ai_provider();
94622
95108
  init_session_store();
94623
95109
  init_outbound_behavior();
95110
+ init_openclaw_route();
94624
95111
  init_paths();
94625
95112
  init_task_config();
94626
95113
  init_sentry_logger();
94627
95114
  init_sentry_config();
95115
+ var CURRENT_GATEWAY_SESSION_KEYS_ENV2 = "OKX_A2A_CURRENT_GATEWAY_SESSION_KEYS";
94628
95116
  function printUsage2() {
94629
- console.log(`okx-a2a ${"0.0.15"}
95117
+ console.log(`okx-a2a ${"0.0.16-beta-d0ec14bc63-260623103149"}
94630
95118
 
94631
95119
  Usage:
94632
95120
  okx-a2a <command> [options]
@@ -94663,7 +95151,7 @@ Run \`okx-a2a <command> -h\` for command-specific help.
94663
95151
  `);
94664
95152
  }
94665
95153
  function printVersion() {
94666
- console.log("0.0.15");
95154
+ console.log("0.0.16-beta-d0ec14bc63-260623103149");
94667
95155
  }
94668
95156
  function printDaemonUsage() {
94669
95157
  console.log(`Usage: okx-a2a daemon <start|restart|stop|status> [options]
@@ -94941,7 +95429,7 @@ async function handleLogs(args) {
94941
95429
  return;
94942
95430
  }
94943
95431
  if (subcommand === "llm") {
94944
- await tailLogFile((0, import_node_path20.join)(paths.logsDir, "llm.log"));
95432
+ await tailLogFile((0, import_node_path21.join)(paths.logsDir, "llm.log"));
94945
95433
  return;
94946
95434
  }
94947
95435
  throw new Error("logs requires <server|llm>");
@@ -94992,11 +95480,39 @@ async function queueXmtpSend(args) {
94992
95480
  sessionAgentId,
94993
95481
  myAgentId: target.myAgentId,
94994
95482
  toAgentId: target.toAgentId,
94995
- toXmtpAddress: toXmtpAddress ?? target.toXmtpAddress
95483
+ toXmtpAddress: toXmtpAddress ?? target.toXmtpAddress,
95484
+ gatewaySessionKeys: readGatewaySessionKeysFromEnv()
94996
95485
  });
94997
95486
  await commands.submit(command);
94998
95487
  console.log(`queued xmtp-send command=${command.id} jobId=${target.jobId}`);
94999
95488
  }
95489
+ function readGatewaySessionKeysFromEnv(env = process.env) {
95490
+ const keys = /* @__PURE__ */ new Set();
95491
+ const list = env[CURRENT_GATEWAY_SESSION_KEYS_ENV2]?.trim();
95492
+ if (list) {
95493
+ try {
95494
+ const parsed = JSON.parse(list);
95495
+ if (Array.isArray(parsed)) {
95496
+ for (const item of parsed) {
95497
+ if (typeof item === "string" && item.trim()) {
95498
+ keys.add(item.trim());
95499
+ }
95500
+ }
95501
+ }
95502
+ } catch {
95503
+ for (const item of list.split(",")) {
95504
+ if (item.trim()) {
95505
+ keys.add(item.trim());
95506
+ }
95507
+ }
95508
+ }
95509
+ }
95510
+ const single = env.OKX_A2A_CURRENT_GATEWAY_SESSION_KEY?.trim();
95511
+ if (single) {
95512
+ keys.add(single);
95513
+ }
95514
+ return keys.size > 0 ? [...keys] : void 0;
95515
+ }
95000
95516
  function resolveXmtpSendTarget(input) {
95001
95517
  if (input.sessionKey) {
95002
95518
  if (input.jobId || input.toAgentId) {
@@ -95337,8 +95853,10 @@ async function dispatchRuntimeSwitchUserMessage(store, result) {
95337
95853
  return;
95338
95854
  }
95339
95855
  try {
95856
+ const sessionKey = result.provider === "openclaw" ? currentOpenClawGatewaySessionKey() ?? void 0 : void 0;
95340
95857
  await createOutboundBehavior(result.provider, { store }).dispatchUser({
95341
95858
  userContent: result.userMessage,
95859
+ ...sessionKey ? { sessionKey } : {},
95342
95860
  idempotencyKey: `runtime-switch:${result.provider}:${result.previousProvider ?? "none"}`
95343
95861
  });
95344
95862
  } catch (err2) {
@@ -95588,11 +96106,11 @@ function initDirectCliSentry() {
95588
96106
  }
95589
96107
  cliSentryInitAttempted = true;
95590
96108
  try {
95591
- const configPath = (0, import_node_path20.join)(resolveTaskHomeForSentryConfig(), "xmtp", "system-config.json");
95592
- if (!(0, import_node_fs16.existsSync)(configPath)) {
96109
+ const configPath = (0, import_node_path21.join)(resolveTaskHomeForSentryConfig(), "xmtp", "system-config.json");
96110
+ if (!(0, import_node_fs17.existsSync)(configPath)) {
95593
96111
  return;
95594
96112
  }
95595
- const config = JSON.parse((0, import_node_fs16.readFileSync)(configPath, "utf8"));
96113
+ const config = JSON.parse((0, import_node_fs17.readFileSync)(configPath, "utf8"));
95596
96114
  if (typeof config.sentryDsn !== "string" || !config.sentryDsn) {
95597
96115
  return;
95598
96116
  }
@@ -95610,13 +96128,13 @@ function resolveTaskHomeForSentryConfig() {
95610
96128
  return process.env.OKX_AGENT_TASK_HOME;
95611
96129
  }
95612
96130
  try {
95613
- const home = (0, import_node_os7.homedir)();
96131
+ const home = (0, import_node_os8.homedir)();
95614
96132
  if (home) {
95615
- return (0, import_node_path20.join)(home, ".okx-agent-task");
96133
+ return (0, import_node_path21.join)(home, ".okx-agent-task");
95616
96134
  }
95617
96135
  } catch {
95618
96136
  }
95619
- return (0, import_node_path20.resolve)(process.cwd(), ".okx-agent-task");
96137
+ return (0, import_node_path21.resolve)(process.cwd(), ".okx-agent-task");
95620
96138
  }
95621
96139
  function directCliSentryExtra(operation, extra = {}) {
95622
96140
  return {