@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/index.js CHANGED
@@ -1913,7 +1913,7 @@ var require_path = __commonJS({
1913
1913
  function isAbsolute2(path) {
1914
1914
  return path.charAt(0) === "/";
1915
1915
  }
1916
- function join18(...args) {
1916
+ function join19(...args) {
1917
1917
  return normalizePath(args.join("/"));
1918
1918
  }
1919
1919
  function dirname6(path) {
@@ -1938,7 +1938,7 @@ var require_path = __commonJS({
1938
1938
  exports2.basename = basename3;
1939
1939
  exports2.dirname = dirname6;
1940
1940
  exports2.isAbsolute = isAbsolute2;
1941
- exports2.join = join18;
1941
+ exports2.join = join19;
1942
1942
  exports2.normalizePath = normalizePath;
1943
1943
  exports2.relative = relative;
1944
1944
  exports2.resolve = resolve4;
@@ -67932,6 +67932,7 @@ __export(index_exports, {
67932
67932
  GatewayOutboundBehavior: () => GatewayOutboundBehavior,
67933
67933
  InvalidXmtpMessageStore: () => InvalidXmtpMessageStore,
67934
67934
  OFFLINE_REPLAY_SYNC_INTERVAL: () => OFFLINE_REPLAY_SYNC_INTERVAL,
67935
+ OPENCLAW_GATEWAY_ROUTE_GROUP_ID: () => OPENCLAW_GATEWAY_ROUTE_GROUP_ID,
67935
67936
  SYSTEM_NOTIFICATION_SESSION_KEY: () => SYSTEM_NOTIFICATION_SESSION_KEY,
67936
67937
  SessionStore: () => SessionStore,
67937
67938
  SqliteOutboundBehavior: () => SqliteOutboundBehavior,
@@ -67945,6 +67946,7 @@ __export(index_exports, {
67945
67946
  bindJobProviderToCurrentDefaultIfMissing: () => bindJobProviderToCurrentDefaultIfMissing,
67946
67947
  bindJobProviderToCurrentRuntimeIfMissing: () => bindJobProviderToCurrentRuntimeIfMissing,
67947
67948
  bindMessageJobProviderToCurrentDefault: () => bindMessageJobProviderToCurrentDefault,
67949
+ bindOpenClawGatewayRouteFromEnv: () => bindOpenClawGatewayRouteFromEnv,
67948
67950
  buildAgentMessageNotice: () => buildAgentMessageNotice,
67949
67951
  buildAiAdapterCommand: () => buildAiAdapterCommand,
67950
67952
  buildAiProviderEnv: () => buildAiProviderEnv,
@@ -67965,6 +67967,7 @@ __export(index_exports, {
67965
67967
  createFileMessageHandler: () => createFileMessageHandler,
67966
67968
  createOutboundBehavior: () => createOutboundBehavior,
67967
67969
  createUserAttentionWatchParentMonitor: () => createUserAttentionWatchParentMonitor,
67970
+ currentOpenClawGatewaySessionKey: () => currentOpenClawGatewaySessionKey,
67968
67971
  detectAiProviders: () => detectAiProviders,
67969
67972
  detectCurrentAiProvider: () => detectCurrentAiProvider,
67970
67973
  detectGatewayInvocation: () => detectGatewayInvocation,
@@ -67998,6 +68001,8 @@ __export(index_exports, {
67998
68001
  resolveConfiguredAiProviderForJob: () => resolveConfiguredAiProviderForJob,
67999
68002
  resolveDirectCommunicationSessionTarget: () => resolveDirectCommunicationSessionTarget,
68000
68003
  resolveOpenClawGatewayConfig: () => resolveOpenClawGatewayConfig,
68004
+ resolveOpenClawGatewayRoute: () => resolveOpenClawGatewayRoute,
68005
+ resolveOpenClawGatewayRoutes: () => resolveOpenClawGatewayRoutes,
68001
68006
  resolveSystemNotificationTargets: () => resolveSystemNotificationTargets,
68002
68007
  resolveTaskConfigPath: () => resolveTaskConfigPath,
68003
68008
  resolveTaskHome: () => resolveTaskHome,
@@ -74210,6 +74215,7 @@ var CommandStore = class {
74210
74215
  myAgentId: params.myAgentId,
74211
74216
  toAgentId: params.toAgentId,
74212
74217
  toXmtpAddress: params.toXmtpAddress,
74218
+ gatewaySessionKeys: params.gatewaySessionKeys,
74213
74219
  createdAt: Date.now()
74214
74220
  };
74215
74221
  }
@@ -86093,7 +86099,7 @@ function buildConnectParams(config, instanceId, protocolVersion) {
86093
86099
  client: {
86094
86100
  id: "gateway-client",
86095
86101
  displayName: "okx-a2a-node",
86096
- version: "0.0.15",
86102
+ version: "0.0.16-beta-d0ec14bc63-260623103149",
86097
86103
  platform: "node",
86098
86104
  mode: "backend",
86099
86105
  instanceId
@@ -86104,7 +86110,7 @@ function buildConnectParams(config, instanceId, protocolVersion) {
86104
86110
  commands: [],
86105
86111
  permissions: {},
86106
86112
  locale: Intl.DateTimeFormat().resolvedOptions().locale || "en-US",
86107
- userAgent: `okx-a2a-node/${"0.0.15"}`,
86113
+ userAgent: `okx-a2a-node/${"0.0.16-beta-d0ec14bc63-260623103149"}`,
86108
86114
  auth: {
86109
86115
  ...config.token ? { token: config.token } : {},
86110
86116
  ...config.password ? { password: config.password } : {}
@@ -86229,6 +86235,319 @@ function safeDecode(value) {
86229
86235
  }
86230
86236
  }
86231
86237
 
86238
+ // src/openclaw-route.ts
86239
+ var import_node_fs13 = require("node:fs");
86240
+ var import_node_os5 = require("node:os");
86241
+ var import_node_path17 = require("node:path");
86242
+ var OPENCLAW_GATEWAY_ROUTE_GROUP_ID = "__openclaw_gateway_route__";
86243
+ var CURRENT_GATEWAY_SESSION_KEYS_ENV = "OKX_A2A_CURRENT_GATEWAY_SESSION_KEYS";
86244
+ var NON_DELIVERY_CHANNELS = /* @__PURE__ */ new Set(["heartbeat", "cron", "webhook", "voice"]);
86245
+ var ACTIVE_ORIGIN_TTL_MS = 30 * 6e4;
86246
+ function currentOpenClawGatewaySessionKey(env = process.env) {
86247
+ for (const candidate of currentOpenClawGatewaySessionCandidates(env)) {
86248
+ if (candidate.ok) {
86249
+ return candidate.sessionKey;
86250
+ }
86251
+ }
86252
+ return null;
86253
+ }
86254
+ function bindOpenClawGatewayRouteFromEnv(store, input, env = process.env) {
86255
+ const jobId = normalizeText(input.jobId);
86256
+ if (!jobId) {
86257
+ return null;
86258
+ }
86259
+ const existingBinding = store.getJobProviderBinding(jobId);
86260
+ if (existingBinding && existingBinding.provider !== "openclaw") {
86261
+ return null;
86262
+ }
86263
+ let routes = readOpenClawRouteEntries(store, jobId);
86264
+ let firstBound = null;
86265
+ for (const candidate of currentOpenClawGatewaySessionCandidates(env, input.gatewaySessionKeys)) {
86266
+ if (!candidate.ok) {
86267
+ logOpenClawRouteSkip(candidate.reason, {
86268
+ jobId,
86269
+ sessionKey: candidate.sessionKey,
86270
+ existingRoute: resolveOpenClawGatewayRoute(store, { jobId })
86271
+ });
86272
+ continue;
86273
+ }
86274
+ const channel = channelFromOpenClawGatewaySessionKey(candidate.sessionKey);
86275
+ if (!channel) {
86276
+ logOpenClawRouteSkip("invalid_gateway_session_key", {
86277
+ jobId,
86278
+ sessionKey: candidate.sessionKey,
86279
+ existingRoute: resolveOpenClawGatewayRoute(store, { jobId })
86280
+ });
86281
+ continue;
86282
+ }
86283
+ const existingRoute = routes.find((route2) => route2.platform === channel) ?? null;
86284
+ if (existingRoute) {
86285
+ firstBound ??= existingRoute.gatewaySessionKey || existingRoute.sessionKey || null;
86286
+ continue;
86287
+ }
86288
+ const route = buildOpenClawRouteEntry(candidate.sessionKey, channel);
86289
+ routes = [...routes, route];
86290
+ const binding = store.upsertJobGatewayRoute({ jobId, provider: "openclaw", route });
86291
+ if (binding.provider !== "openclaw") {
86292
+ return null;
86293
+ }
86294
+ firstBound ??= route.gatewaySessionKey || route.sessionKey || null;
86295
+ }
86296
+ if (firstBound) {
86297
+ return firstBound;
86298
+ }
86299
+ return resolveOpenClawGatewayRoute(store, { jobId })?.sessionKey ?? null;
86300
+ }
86301
+ function currentOpenClawGatewaySessionCandidates(env = process.env, explicitSessionKeys) {
86302
+ const platform = normalizeText(env.OKX_A2A_CURRENT_GATEWAY_PLATFORM);
86303
+ const chatId = normalizeText(env.OKX_A2A_CURRENT_GATEWAY_CHAT_ID);
86304
+ const threadId = normalizeText(env.OKX_A2A_CURRENT_GATEWAY_THREAD_ID);
86305
+ const rawKeys = [
86306
+ ...Array.isArray(explicitSessionKeys) ? explicitSessionKeys : [],
86307
+ ...readGatewaySessionKeysEnv(env),
86308
+ normalizeText(env.OKX_A2A_CURRENT_GATEWAY_SESSION_KEY),
86309
+ platform && chatId ? deriveOpenClawGatewaySessionKey({ platform, chatId, threadId }) : null,
86310
+ normalizeText(env.OKX_A2A_CURRENT_SESSION_KEY),
86311
+ ...readSingleActiveOriginSessionKey(env)
86312
+ ];
86313
+ const seen = /* @__PURE__ */ new Set();
86314
+ const candidates = [];
86315
+ for (const key of rawKeys) {
86316
+ const normalized = normalizeText(key);
86317
+ if (!normalized || seen.has(normalized)) {
86318
+ continue;
86319
+ }
86320
+ seen.add(normalized);
86321
+ candidates.push(validateOpenClawGatewaySessionKey(normalized));
86322
+ }
86323
+ if (candidates.length > 0) {
86324
+ return candidates;
86325
+ }
86326
+ return [{ ok: false, reason: "missing_gateway_session_key" }];
86327
+ }
86328
+ function resolveOpenClawGatewayRoute(store, input) {
86329
+ return resolveOpenClawGatewayRoutes(store, input)[0] ?? null;
86330
+ }
86331
+ function resolveOpenClawGatewayRoutes(store, input) {
86332
+ const jobId = normalizeText(input.jobId) ?? inferJobIdFromSessionKey2(normalizeText(input.sessionKey));
86333
+ if (jobId) {
86334
+ return readOpenClawRouteEntries(store, jobId).map((route) => toOpenClawGatewayRoute(route, jobId));
86335
+ }
86336
+ return [];
86337
+ }
86338
+ function isValidOpenClawGatewaySessionKey(sessionKey) {
86339
+ return validateOpenClawGatewaySessionKey(sessionKey).ok;
86340
+ }
86341
+ function buildOpenClawRouteEntry(sessionKey, channel) {
86342
+ const parsed = parseOpenClawGatewaySessionKey(sessionKey);
86343
+ return {
86344
+ platform: channel,
86345
+ chatId: parsed.chatId ?? sessionKey,
86346
+ chatType: parsed.threadId ? "thread" : "dm",
86347
+ sessionKey,
86348
+ gatewaySessionKey: sessionKey,
86349
+ chatName: "",
86350
+ ...parsed.threadId ? { threadId: parsed.threadId } : { threadId: "" },
86351
+ userId: "",
86352
+ userName: "",
86353
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
86354
+ };
86355
+ }
86356
+ function toOpenClawGatewayRoute(route, jobId) {
86357
+ const sessionKey = route.gatewaySessionKey || route.sessionKey || "";
86358
+ return {
86359
+ sessionKey,
86360
+ jobId,
86361
+ routeSessionKey: route.sessionKey || sessionKey,
86362
+ updatedAt: route.updatedAt ?? "",
86363
+ channel: route.platform
86364
+ };
86365
+ }
86366
+ function readOpenClawRouteEntries(store, jobId) {
86367
+ const binding = store?.getJobProviderBinding(jobId);
86368
+ if (binding?.provider !== "openclaw") {
86369
+ return [];
86370
+ }
86371
+ const routes = binding.gatewayRoutes ?? [];
86372
+ const seenChannels = /* @__PURE__ */ new Set();
86373
+ const validRoutes = [];
86374
+ for (const route of routes) {
86375
+ const sessionKey = normalizeText(route.gatewaySessionKey) ?? normalizeText(route.sessionKey);
86376
+ const channel = channelFromOpenClawGatewaySessionKey(sessionKey);
86377
+ if (!sessionKey || !channel || seenChannels.has(channel)) {
86378
+ continue;
86379
+ }
86380
+ seenChannels.add(channel);
86381
+ validRoutes.push({
86382
+ platform: channel,
86383
+ chatId: route.chatId,
86384
+ chatName: route.chatName ?? "",
86385
+ chatType: route.chatType || (route.threadId ? "thread" : "dm"),
86386
+ sessionKey: route.sessionKey,
86387
+ gatewaySessionKey: sessionKey,
86388
+ threadId: route.threadId ?? "",
86389
+ userId: route.userId ?? "",
86390
+ userName: route.userName ?? "",
86391
+ ...route.updatedAt ? { updatedAt: route.updatedAt } : {}
86392
+ });
86393
+ }
86394
+ return validRoutes;
86395
+ }
86396
+ function parseOpenClawGatewaySessionKey(sessionKey) {
86397
+ const parts = sessionKey.split(":");
86398
+ if (parts.length < 4 || parts[0] !== "agent") {
86399
+ return {};
86400
+ }
86401
+ const platform = parts[2];
86402
+ const targetKind = parts[3];
86403
+ if (platform === "discord" && targetKind === "thread") {
86404
+ return {
86405
+ ...parts[4] ? { chatId: parts[4] } : {},
86406
+ ...parts[5] ? { threadId: parts[5] } : {}
86407
+ };
86408
+ }
86409
+ if (platform === "discord" && targetKind === "channel") {
86410
+ return parts[4] ? { chatId: parts[4] } : {};
86411
+ }
86412
+ if (platform === "discord" && targetKind === "dm") {
86413
+ return parts[4] ? { chatId: parts[4] } : {};
86414
+ }
86415
+ if (platform === "telegram" && targetKind === "direct") {
86416
+ return parts[4] ? { chatId: parts[4] } : {};
86417
+ }
86418
+ if (platform === "telegram" && targetKind === "group") {
86419
+ return {
86420
+ ...parts[4] ? { chatId: parts[4] } : {},
86421
+ ...parts[6] ? { threadId: parts[6] } : {}
86422
+ };
86423
+ }
86424
+ return {};
86425
+ }
86426
+ function validateOpenClawGatewaySessionKey(sessionKey) {
86427
+ const key = normalizeText(sessionKey);
86428
+ if (!key) {
86429
+ return { ok: false, reason: "missing_gateway_session_key" };
86430
+ }
86431
+ if (key.startsWith("backup:")) {
86432
+ return { ok: false, reason: "internal_gateway_session_key", sessionKey: key };
86433
+ }
86434
+ if (key === "agent:main") {
86435
+ return { ok: true, sessionKey: key };
86436
+ }
86437
+ const parts = key.split(":");
86438
+ if (parts.length < 4 || parts[0] !== "agent" || !parts[1]) {
86439
+ return { ok: false, reason: "invalid_gateway_session_key", sessionKey: key };
86440
+ }
86441
+ const platform = parts[2];
86442
+ if (!platform || platform === "okx-a2a" || NON_DELIVERY_CHANNELS.has(platform)) {
86443
+ return { ok: false, reason: "internal_gateway_session_key", sessionKey: key };
86444
+ }
86445
+ return { ok: true, sessionKey: key };
86446
+ }
86447
+ function channelFromOpenClawGatewaySessionKey(sessionKey) {
86448
+ const key = normalizeText(sessionKey);
86449
+ if (!key) {
86450
+ return null;
86451
+ }
86452
+ if (key === "agent:main") {
86453
+ return "main";
86454
+ }
86455
+ const validation = validateOpenClawGatewaySessionKey(key);
86456
+ if (!validation.ok) {
86457
+ return null;
86458
+ }
86459
+ return key.split(":")[2] ?? null;
86460
+ }
86461
+ function deriveOpenClawGatewaySessionKey(input) {
86462
+ const chatId = encodeURIComponent(input.chatId);
86463
+ const threadId = input.threadId ? encodeURIComponent(input.threadId) : "";
86464
+ if (input.platform === "telegram") {
86465
+ return threadId ? `agent:main:telegram:group:${chatId}:topic:${threadId}` : `agent:main:telegram:direct:${chatId}`;
86466
+ }
86467
+ return threadId ? `agent:main:${input.platform}:thread:${chatId}:${threadId}` : `agent:main:${input.platform}:dm:${chatId}`;
86468
+ }
86469
+ function readGatewaySessionKeysEnv(env) {
86470
+ const raw = normalizeText(env[CURRENT_GATEWAY_SESSION_KEYS_ENV]);
86471
+ if (!raw) {
86472
+ return [];
86473
+ }
86474
+ try {
86475
+ const parsed = JSON.parse(raw);
86476
+ if (Array.isArray(parsed)) {
86477
+ return parsed.filter((item) => typeof item === "string" && item.trim().length > 0);
86478
+ }
86479
+ } catch {
86480
+ }
86481
+ return raw.split(",").map((item) => item.trim()).filter(Boolean);
86482
+ }
86483
+ function readSingleActiveOriginSessionKey(env) {
86484
+ const path = (0, import_node_path17.join)(resolveTaskHome2(env), "run", "gateway-route-origins.json");
86485
+ if (!(0, import_node_fs13.existsSync)(path)) {
86486
+ return [];
86487
+ }
86488
+ try {
86489
+ const parsed = JSON.parse((0, import_node_fs13.readFileSync)(path, "utf8"));
86490
+ if (!isRecord2(parsed) || !Array.isArray(parsed.origins)) {
86491
+ return [];
86492
+ }
86493
+ const now = Date.now();
86494
+ const valid = parsed.origins.filter((item) => isRecord2(item)).map((item) => ({
86495
+ sessionKey: normalizeText(typeof item.sessionKey === "string" ? item.sessionKey : null),
86496
+ count: typeof item.count === "number" && Number.isFinite(item.count) ? item.count : 0,
86497
+ updatedAt: typeof item.updatedAt === "number" && Number.isFinite(item.updatedAt) ? item.updatedAt : 0
86498
+ })).filter((item) => item.sessionKey && item.count > 0 && now - item.updatedAt <= ACTIVE_ORIGIN_TTL_MS && validateOpenClawGatewaySessionKey(item.sessionKey).ok);
86499
+ const sessionKeys = [...new Set(valid.map((item) => item.sessionKey).filter(Boolean))];
86500
+ return sessionKeys.length === 1 ? sessionKeys : [];
86501
+ } catch (err2) {
86502
+ console.error(
86503
+ `[openclaw-route] failed to read active gateway route origin state: ${err2 instanceof Error ? err2.message : String(err2)}`
86504
+ );
86505
+ return [];
86506
+ }
86507
+ }
86508
+ function resolveTaskHome2(env) {
86509
+ return env.OKX_AGENT_TASK_HOME?.trim() || (0, import_node_path17.join)((0, import_node_os5.homedir)(), ".okx-agent-task");
86510
+ }
86511
+ function logOpenClawRouteSkip(reason, input) {
86512
+ if (reason === "missing_gateway_session_key") {
86513
+ return;
86514
+ }
86515
+ console.error(
86516
+ `[openclaw-route] skipped gateway route bind reason=${reason} jobId=${input.jobId} sessionKey=${input.sessionKey ?? "(none)"} existingRoute=${input.existingRoute?.sessionKey ?? "(none)"}`
86517
+ );
86518
+ }
86519
+ function inferJobIdFromSessionKey2(sessionKey) {
86520
+ if (!sessionKey) {
86521
+ return null;
86522
+ }
86523
+ const parts = sessionKey.split(":");
86524
+ if (parts.length >= 2 && parts[0] === "job") {
86525
+ return safeDecode2(parts[1]);
86526
+ }
86527
+ if (sessionKey.startsWith("backup:")) {
86528
+ return safeDecode2(sessionKey.slice("backup:".length));
86529
+ }
86530
+ const gatewayJob = /(?:^|[?&:])job=([^:&]+)/.exec(sessionKey);
86531
+ if (gatewayJob?.[1]) {
86532
+ return safeDecode2(gatewayJob[1]);
86533
+ }
86534
+ return null;
86535
+ }
86536
+ function normalizeText(value) {
86537
+ const text = value?.trim();
86538
+ return text ? text : null;
86539
+ }
86540
+ function isRecord2(value) {
86541
+ return typeof value === "object" && value !== null && !Array.isArray(value);
86542
+ }
86543
+ function safeDecode2(value) {
86544
+ try {
86545
+ return decodeURIComponent(value);
86546
+ } catch {
86547
+ return value;
86548
+ }
86549
+ }
86550
+
86232
86551
  // src/outbound-behavior.ts
86233
86552
  var SqliteOutboundBehavior = class {
86234
86553
  provider;
@@ -86316,7 +86635,7 @@ function assertLatestUserFanoutDelivered(operation, payload) {
86316
86635
  const result = payload;
86317
86636
  const dispatched = Array.isArray(result.dispatched) ? result.dispatched.length : null;
86318
86637
  const failed = Array.isArray(result.failed) ? result.failed.length : null;
86319
- if (result.ok === false || dispatched === 0) {
86638
+ if (dispatched === 0 || result.ok === false && dispatched === null) {
86320
86639
  throw Object.assign(
86321
86640
  new Error(
86322
86641
  `${operation} did not deliver to any OpenClaw user session (dispatched=${dispatched ?? "unknown"} failed=${failed ?? "unknown"})`
@@ -86450,11 +86769,20 @@ var GatewayOutboundBehavior = class {
86450
86769
  });
86451
86770
  }
86452
86771
  async dispatchUser(input) {
86772
+ const routed = this.resolveUserGatewaySessionKey(input);
86773
+ if (routed) {
86774
+ await this.dispatchUserToGatewaySession(input, routed);
86775
+ return null;
86776
+ }
86453
86777
  errorWithTimestamp(
86454
86778
  `${GATEWAY_OUTBOUND_LOG_PREFIX} dispatchUser latestUserSessions jobId=${input.jobId ?? "(none)"} idempotencyKey=${input.idempotencyKey ?? "(none)"}`
86455
86779
  );
86456
86780
  try {
86457
- const result = await this.gateway.callDispatchUserToLatestSessions({ content: input.userContent });
86781
+ const result = await this.gateway.callDispatchUserToLatestSessions({
86782
+ content: input.userContent,
86783
+ ...input.jobId ? { jobId: input.jobId } : {},
86784
+ ...input.sessionKey ? { currentSessionKey: input.sessionKey } : {}
86785
+ });
86458
86786
  assertLatestUserFanoutDelivered("okx-a2a.dispatch_user", result);
86459
86787
  errorWithTimestamp(`${GATEWAY_OUTBOUND_LOG_PREFIX} dispatchUser latestUserSessions ok`);
86460
86788
  logger.info(LogEvent.USER_DISPATCHED, gatewayOutboundExtra("okx-a2a.dispatch_user", {
@@ -86492,14 +86820,90 @@ var GatewayOutboundBehavior = class {
86492
86820
  }
86493
86821
  return null;
86494
86822
  }
86823
+ resolveUserGatewaySessionKey(input) {
86824
+ const routes = resolveOpenClawGatewayRoutes(this.sessionMetaStore, input);
86825
+ if (routes.length > 0) {
86826
+ return { sessionKeys: routes.map((route) => route.sessionKey), source: "stored_openclaw_routes" };
86827
+ }
86828
+ if (input.sessionKey?.startsWith("agent:")) {
86829
+ return isValidOpenClawGatewaySessionKey(input.sessionKey) ? { sessionKeys: [input.sessionKey], source: "explicit_gateway_session" } : null;
86830
+ }
86831
+ return null;
86832
+ }
86833
+ async dispatchUserToGatewaySession(input, routed) {
86834
+ const gatewaySessionKey = routed.sessionKeys.join(",");
86835
+ console.error(
86836
+ `${GATEWAY_OUTBOUND_LOG_PREFIX} dispatchUser routed sessionKey=${input.sessionKey ?? "(none)"} gatewaySessionKey=${gatewaySessionKey} source=${routed.source} jobId=${input.jobId ?? "(none)"} idempotencyKey=${input.idempotencyKey ?? "(none)"}`
86837
+ );
86838
+ try {
86839
+ const result = await this.gateway.callDispatchUserToLatestSessions({
86840
+ content: input.userContent,
86841
+ label: "okx-a2a",
86842
+ ...routed.source === "stored_openclaw_routes" ? { sessionKeys: routed.sessionKeys } : { sessionKey: routed.sessionKeys[0] }
86843
+ });
86844
+ assertLatestUserFanoutDelivered("okx-a2a.dispatch_user", result);
86845
+ console.error(`${GATEWAY_OUTBOUND_LOG_PREFIX} dispatchUser routed ok gatewaySessionKey=${gatewaySessionKey} source=${routed.source}`);
86846
+ logger.info(LogEvent.USER_DISPATCHED, gatewayOutboundExtra("okx-a2a.dispatch_user", {
86847
+ sessionKey: input.sessionKey ?? "",
86848
+ gatewaySessionKey,
86849
+ jobId: input.jobId ?? "",
86850
+ source: routed.source,
86851
+ status: "delivered"
86852
+ }));
86853
+ } catch (err2) {
86854
+ if (!this.store || !isRetryableOpenClawGatewayError(err2)) {
86855
+ logger.error(LogEvent.USER_DISPATCH_FAILED, err2 instanceof Error ? err2 : new Error(String(err2)), gatewayOutboundExtra("okx-a2a.dispatch_user", {
86856
+ sessionKey: input.sessionKey ?? "",
86857
+ gatewaySessionKey,
86858
+ jobId: input.jobId ?? "",
86859
+ source: routed.source,
86860
+ status: "failed"
86861
+ }));
86862
+ throw err2;
86863
+ }
86864
+ this.store.enqueuePendingGatewayDelivery({
86865
+ kind: "chat_inject",
86866
+ provider: this.provider,
86867
+ sessionKey: routed.sessionKeys[0] ?? "openclaw:routed-user-sessions",
86868
+ content: input.userContent,
86869
+ jobId: input.jobId ?? null,
86870
+ messageId: input.idempotencyKey ?? null
86871
+ });
86872
+ console.error(
86873
+ `${GATEWAY_OUTBOUND_LOG_PREFIX} dispatchUser routed buffered gatewaySessionKey=${gatewaySessionKey} source=${routed.source} idempotencyKey=${input.idempotencyKey ?? "(none)"}: ${err2 instanceof Error ? err2.message : String(err2)}`
86874
+ );
86875
+ logger.error(LogEvent.USER_DISPATCH_FAILED, err2 instanceof Error ? err2 : new Error(String(err2)), gatewayOutboundExtra("okx-a2a.dispatch_user", {
86876
+ sessionKey: input.sessionKey ?? "",
86877
+ gatewaySessionKey,
86878
+ jobId: input.jobId ?? "",
86879
+ source: routed.source,
86880
+ status: "buffered"
86881
+ }));
86882
+ logger.info(LogEvent.GATEWAY_DELIVERY_BUFFERED, gatewayOutboundExtra("okx-a2a.dispatch_user", {
86883
+ sessionKey: input.sessionKey ?? "",
86884
+ gatewaySessionKey,
86885
+ jobId: input.jobId ?? "",
86886
+ messageId: input.idempotencyKey ?? "",
86887
+ source: routed.source,
86888
+ status: "buffered"
86889
+ }));
86890
+ }
86891
+ }
86495
86892
  async promptUser(input) {
86893
+ const routed = this.resolveUserGatewaySessionKey(input);
86894
+ if (routed) {
86895
+ await this.promptUserToGatewaySession(input, routed);
86896
+ return null;
86897
+ }
86496
86898
  errorWithTimestamp(
86497
86899
  `${GATEWAY_OUTBOUND_LOG_PREFIX} promptUser latestUserSessions jobId=${input.jobId ?? "(none)"} idempotencyKey=${input.idempotencyKey ?? "(none)"}`
86498
86900
  );
86499
86901
  try {
86500
86902
  const result = await this.gateway.callPromptUserToLatestSessions({
86501
86903
  userContent: input.userContent,
86502
- llmContent: input.llmContent
86904
+ llmContent: input.llmContent,
86905
+ ...input.jobId ? { jobId: input.jobId } : {},
86906
+ ...input.sessionKey ? { currentSessionKey: input.sessionKey } : {}
86503
86907
  });
86504
86908
  assertLatestUserFanoutDelivered("okx-a2a.prompt_user", result);
86505
86909
  errorWithTimestamp(`${GATEWAY_OUTBOUND_LOG_PREFIX} promptUser latestUserSessions ok`);
@@ -86539,6 +86943,66 @@ var GatewayOutboundBehavior = class {
86539
86943
  }
86540
86944
  return null;
86541
86945
  }
86946
+ async promptUserToGatewaySession(input, routed) {
86947
+ const gatewaySessionKey = routed.sessionKeys.join(",");
86948
+ console.error(
86949
+ `${GATEWAY_OUTBOUND_LOG_PREFIX} promptUser routed sessionKey=${input.sessionKey ?? "(none)"} gatewaySessionKey=${gatewaySessionKey} source=${routed.source} jobId=${input.jobId ?? "(none)"} idempotencyKey=${input.idempotencyKey ?? "(none)"}`
86950
+ );
86951
+ try {
86952
+ const result = await this.gateway.callPromptUserToLatestSessions({
86953
+ userContent: input.userContent,
86954
+ llmContent: input.llmContent,
86955
+ ...routed.source === "stored_openclaw_routes" ? { sessionKeys: routed.sessionKeys } : { sessionKey: routed.sessionKeys[0] }
86956
+ });
86957
+ assertLatestUserFanoutDelivered("okx-a2a.prompt_user", result);
86958
+ console.error(`${GATEWAY_OUTBOUND_LOG_PREFIX} promptUser routed ok gatewaySessionKey=${gatewaySessionKey} source=${routed.source}`);
86959
+ logger.info(LogEvent.PROMPT_USER_CHECKPOINT, gatewayOutboundExtra("routed_prompt_user", {
86960
+ sessionKey: input.sessionKey ?? "",
86961
+ gatewaySessionKey,
86962
+ jobId: input.jobId ?? "",
86963
+ source: routed.source,
86964
+ status: "delivered"
86965
+ }));
86966
+ } catch (err2) {
86967
+ if (!this.store || !isRetryableOpenClawGatewayError(err2)) {
86968
+ logger.error(LogEvent.PROMPT_USER_FAILED, err2 instanceof Error ? err2 : new Error(String(err2)), gatewayOutboundExtra("routed_prompt_user", {
86969
+ sessionKey: input.sessionKey ?? "",
86970
+ gatewaySessionKey,
86971
+ jobId: input.jobId ?? "",
86972
+ source: routed.source,
86973
+ status: "failed"
86974
+ }));
86975
+ throw err2;
86976
+ }
86977
+ this.store.enqueuePendingGatewayDelivery({
86978
+ kind: "chat_inject",
86979
+ provider: this.provider,
86980
+ sessionKey: routed.sessionKeys[0] ?? "openclaw:routed-user-sessions",
86981
+ content: input.userContent,
86982
+ llmContent: input.llmContent,
86983
+ jobId: input.jobId ?? null,
86984
+ messageId: input.idempotencyKey ?? null
86985
+ });
86986
+ console.error(
86987
+ `${GATEWAY_OUTBOUND_LOG_PREFIX} promptUser routed buffered gatewaySessionKey=${gatewaySessionKey} source=${routed.source} idempotencyKey=${input.idempotencyKey ?? "(none)"}: ${err2 instanceof Error ? err2.message : String(err2)}`
86988
+ );
86989
+ logger.error(LogEvent.PROMPT_USER_FAILED, err2 instanceof Error ? err2 : new Error(String(err2)), gatewayOutboundExtra("routed_prompt_user", {
86990
+ sessionKey: input.sessionKey ?? "",
86991
+ gatewaySessionKey,
86992
+ jobId: input.jobId ?? "",
86993
+ source: routed.source,
86994
+ status: "buffered"
86995
+ }));
86996
+ logger.info(LogEvent.GATEWAY_DELIVERY_BUFFERED, gatewayOutboundExtra("routed_prompt_user", {
86997
+ sessionKey: input.sessionKey ?? "",
86998
+ gatewaySessionKey,
86999
+ jobId: input.jobId ?? "",
87000
+ messageId: input.idempotencyKey ?? "",
87001
+ source: routed.source,
87002
+ status: "buffered"
87003
+ }));
87004
+ }
87005
+ }
86542
87006
  };
86543
87007
  function createOutboundBehavior(provider, deps) {
86544
87008
  if (provider === "openclaw") {
@@ -86627,15 +87091,27 @@ function resolveOutboundProvider(store, input) {
86627
87091
  if (input.override) {
86628
87092
  return input.override;
86629
87093
  }
87094
+ if (input.jobId && resolveOpenClawGatewayRoute(store, { jobId: input.jobId })) {
87095
+ return "openclaw";
87096
+ }
86630
87097
  try {
86631
- return resolveConfiguredAiProviderForJob({
87098
+ const configured = resolveConfiguredAiProviderForJob({
86632
87099
  store,
86633
87100
  jobId: input.jobId,
86634
87101
  env: process.env
86635
- }) ?? "codex";
87102
+ });
87103
+ if (configured) {
87104
+ return configured;
87105
+ }
86636
87106
  } catch {
86637
- return "codex";
86638
87107
  }
87108
+ if (readSyncedOpenClawGatewayConfig(store.homeDir)) {
87109
+ if (input.jobId?.trim()) {
87110
+ return store.bindJobProviderIfMissing({ jobId: input.jobId.trim(), provider: "openclaw" }).binding.provider;
87111
+ }
87112
+ return "openclaw";
87113
+ }
87114
+ return "codex";
86639
87115
  }
86640
87116
  async function notifyAgentMessageToUserAttention(input) {
86641
87117
  const ownedStore = input.store ? null : new SessionStore();
@@ -86767,6 +87243,9 @@ function bindOutboundJobProviderToCurrentDefault(sessionStore, jobId) {
86767
87243
  logWithTimestamp(`[okx-agent-task] job provider bind failed from outbound-xmtp: job=${jobId}`, err2);
86768
87244
  }
86769
87245
  }
87246
+ function bindOutboundOpenClawRouteIfCurrent(sessionStore, jobId, gatewaySessionKeys) {
87247
+ bindOpenClawGatewayRouteFromEnv(sessionStore, { jobId, gatewaySessionKeys });
87248
+ }
86770
87249
  function buildTaskPayload(replyToMessageId) {
86771
87250
  return {
86772
87251
  taskMinVersion: TASK_MIN_VERSION,
@@ -87203,6 +87682,7 @@ async function handleSqliteGroupSendCommand(params) {
87203
87682
  myAgentXmtpAddress: myXmtpAddress,
87204
87683
  toAgentXmtpAddress: remote.toXmtpAddress
87205
87684
  });
87685
+ bindOutboundOpenClawRouteIfCurrent(sessionStore, command.jobId, command.gatewaySessionKeys);
87206
87686
  return { conversation: conversation2, created: created2 };
87207
87687
  }
87208
87688
  );
@@ -87529,7 +88009,7 @@ async function handleXmtpSendCommand(params) {
87529
88009
  const sessionStore2 = params.sessionStore ?? ownedStore2;
87530
88010
  try {
87531
88011
  bindOutboundJobProviderToCurrentDefault(sessionStore2, command.jobId);
87532
- resolveConfiguredAiProviderForJob({ store: sessionStore2, jobId: command.jobId });
88012
+ bindOutboundOpenClawRouteIfCurrent(sessionStore2, command.jobId, command.gatewaySessionKeys);
87533
88013
  return await handleSqliteGroupSendCommand({
87534
88014
  command,
87535
88015
  service,
@@ -87543,7 +88023,7 @@ async function handleXmtpSendCommand(params) {
87543
88023
  const sessionStore = params.sessionStore ?? ownedStore;
87544
88024
  try {
87545
88025
  bindOutboundJobProviderToCurrentDefault(sessionStore, command.jobId);
87546
- resolveConfiguredAiProviderForJob({ store: sessionStore, jobId: command.jobId });
88026
+ bindOutboundOpenClawRouteIfCurrent(sessionStore, command.jobId, command.gatewaySessionKeys);
87547
88027
  const { file, sessionAgentId } = await readFileForSend({
87548
88028
  command,
87549
88029
  store,
@@ -89650,7 +90130,7 @@ function userWatchEventDeliveredSentryExtra(event) {
89650
90130
  var environment = process.env.SENTRY_ENV === "dev" ? "dev" : "prod";
89651
90131
  var SENTRY_CONFIG = {
89652
90132
  projectName: "okx/openclaw-okx-a2a-extension",
89653
- release: "0.0.15",
90133
+ release: "0.0.16-beta-d0ec14bc63-260623103149",
89654
90134
  environment
89655
90135
  };
89656
90136
 
@@ -89771,12 +90251,12 @@ async function runListenerWithLock(options, paths) {
89771
90251
  }));
89772
90252
  }
89773
90253
  });
89774
- service.setPluginVersion("0.0.15");
90254
+ service.setPluginVersion("0.0.16-beta-d0ec14bc63-260623103149");
89775
90255
  await service.init();
89776
90256
  const pluginVersionStatus = service.pluginVersionStatus;
89777
90257
  if (pluginVersionStatus.unavailable) {
89778
90258
  throw new Error(
89779
- `@okxweb3/a2a-node v${"0.0.15"} is below the required minimum v${pluginVersionStatus.minVersion}`
90259
+ `@okxweb3/a2a-node v${"0.0.16-beta-d0ec14bc63-260623103149"} is below the required minimum v${pluginVersionStatus.minVersion}`
89780
90260
  );
89781
90261
  }
89782
90262
  const systemConfig = service.getSystemConfig();
@@ -89794,7 +90274,7 @@ async function runListenerWithLock(options, paths) {
89794
90274
  onchainosAgentId: "*",
89795
90275
  reason: "system-config missing sentryDsn",
89796
90276
  pluginId: "@okxweb3/a2a-node",
89797
- pluginVersion: "0.0.15"
90277
+ pluginVersion: "0.0.16-beta-d0ec14bc63-260623103149"
89798
90278
  });
89799
90279
  }
89800
90280
  logWithTimestamp(
@@ -89963,8 +90443,8 @@ async function timeSettled(fn) {
89963
90443
 
89964
90444
  // src/update-cli.ts
89965
90445
  var import_promises6 = require("node:fs/promises");
89966
- var import_node_os5 = require("node:os");
89967
- var import_node_path17 = require("node:path");
90446
+ var import_node_os6 = require("node:os");
90447
+ var import_node_path18 = require("node:path");
89968
90448
  function isPrereleaseVersion(version2) {
89969
90449
  return /\d+\.\d+\.\d+-[0-9A-Za-z.-]+/.test(version2);
89970
90450
  }
@@ -90095,7 +90575,7 @@ function isEmptyInlineEnabledList(line) {
90095
90575
  return !!inline && inline.values.length === 0;
90096
90576
  }
90097
90577
  function resolveHermesConfigPath() {
90098
- return (0, import_node_path17.join)(process.env.HERMES_HOME ?? (0, import_node_path17.join)((0, import_node_os5.homedir)(), ".hermes"), "config.yaml");
90578
+ return (0, import_node_path18.join)(process.env.HERMES_HOME ?? (0, import_node_path18.join)((0, import_node_os6.homedir)(), ".hermes"), "config.yaml");
90099
90579
  }
90100
90580
  function lineIndent(line) {
90101
90581
  const match = line.match(/^\s*/);
@@ -90167,6 +90647,7 @@ function parsePluginYamlVersion(content3) {
90167
90647
  GatewayOutboundBehavior,
90168
90648
  InvalidXmtpMessageStore,
90169
90649
  OFFLINE_REPLAY_SYNC_INTERVAL,
90650
+ OPENCLAW_GATEWAY_ROUTE_GROUP_ID,
90170
90651
  SYSTEM_NOTIFICATION_SESSION_KEY,
90171
90652
  SessionStore,
90172
90653
  SqliteOutboundBehavior,
@@ -90180,6 +90661,7 @@ function parsePluginYamlVersion(content3) {
90180
90661
  bindJobProviderToCurrentDefaultIfMissing,
90181
90662
  bindJobProviderToCurrentRuntimeIfMissing,
90182
90663
  bindMessageJobProviderToCurrentDefault,
90664
+ bindOpenClawGatewayRouteFromEnv,
90183
90665
  buildAgentMessageNotice,
90184
90666
  buildAiAdapterCommand,
90185
90667
  buildAiProviderEnv,
@@ -90200,6 +90682,7 @@ function parsePluginYamlVersion(content3) {
90200
90682
  createFileMessageHandler,
90201
90683
  createOutboundBehavior,
90202
90684
  createUserAttentionWatchParentMonitor,
90685
+ currentOpenClawGatewaySessionKey,
90203
90686
  detectAiProviders,
90204
90687
  detectCurrentAiProvider,
90205
90688
  detectGatewayInvocation,
@@ -90233,6 +90716,8 @@ function parsePluginYamlVersion(content3) {
90233
90716
  resolveConfiguredAiProviderForJob,
90234
90717
  resolveDirectCommunicationSessionTarget,
90235
90718
  resolveOpenClawGatewayConfig,
90719
+ resolveOpenClawGatewayRoute,
90720
+ resolveOpenClawGatewayRoutes,
90236
90721
  resolveSystemNotificationTargets,
90237
90722
  resolveTaskConfigPath,
90238
90723
  resolveTaskHome,