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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/dist/cli.js +700 -167
  2. package/dist/index.js +511 -19
  3. package/package.json +1 -1
package/dist/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-260623110312",
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-260623110312"}`,
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"})`
@@ -86382,6 +86701,7 @@ var GatewayOutboundBehavior = class {
86382
86701
  }
86383
86702
  async dispatchSessionMessage(input) {
86384
86703
  const gatewaySessionKey = this.resolveGatewaySessionKey(input);
86704
+ this.bindUserRouteForJob(input.jobId);
86385
86705
  errorWithTimestamp(
86386
86706
  `${GATEWAY_OUTBOUND_LOG_PREFIX} dispatchSessionMessage sessionKey=${input.sessionKey} gatewaySessionKey=${gatewaySessionKey} jobId=${input.jobId ?? "(none)"} agentId=${input.agentId ?? "(none)"} messageId=${input.messageId ?? "(none)"}`
86387
86707
  );
@@ -86439,6 +86759,12 @@ var GatewayOutboundBehavior = class {
86439
86759
  }));
86440
86760
  }
86441
86761
  }
86762
+ bindUserRouteForJob(jobId) {
86763
+ if (!this.store || !jobId) {
86764
+ return;
86765
+ }
86766
+ bindOpenClawGatewayRouteFromEnv(this.store, { jobId });
86767
+ }
86442
86768
  resolveGatewaySessionKey(input) {
86443
86769
  const stored = this.sessionMetaStore?.getSession(input.sessionKey);
86444
86770
  return toOpenClawGatewaySessionKey({
@@ -86450,11 +86776,20 @@ var GatewayOutboundBehavior = class {
86450
86776
  });
86451
86777
  }
86452
86778
  async dispatchUser(input) {
86779
+ const routed = this.resolveUserGatewaySessionKey(input);
86780
+ if (routed) {
86781
+ await this.dispatchUserToGatewaySession(input, routed);
86782
+ return null;
86783
+ }
86453
86784
  errorWithTimestamp(
86454
86785
  `${GATEWAY_OUTBOUND_LOG_PREFIX} dispatchUser latestUserSessions jobId=${input.jobId ?? "(none)"} idempotencyKey=${input.idempotencyKey ?? "(none)"}`
86455
86786
  );
86456
86787
  try {
86457
- const result = await this.gateway.callDispatchUserToLatestSessions({ content: input.userContent });
86788
+ const result = await this.gateway.callDispatchUserToLatestSessions({
86789
+ content: input.userContent,
86790
+ ...input.jobId ? { jobId: input.jobId } : {},
86791
+ ...input.sessionKey ? { currentSessionKey: input.sessionKey } : {}
86792
+ });
86458
86793
  assertLatestUserFanoutDelivered("okx-a2a.dispatch_user", result);
86459
86794
  errorWithTimestamp(`${GATEWAY_OUTBOUND_LOG_PREFIX} dispatchUser latestUserSessions ok`);
86460
86795
  logger.info(LogEvent.USER_DISPATCHED, gatewayOutboundExtra("okx-a2a.dispatch_user", {
@@ -86492,14 +86827,90 @@ var GatewayOutboundBehavior = class {
86492
86827
  }
86493
86828
  return null;
86494
86829
  }
86830
+ resolveUserGatewaySessionKey(input) {
86831
+ const routes = resolveOpenClawGatewayRoutes(this.sessionMetaStore, input);
86832
+ if (routes.length > 0) {
86833
+ return { sessionKeys: routes.map((route) => route.sessionKey), source: "stored_openclaw_routes" };
86834
+ }
86835
+ if (input.sessionKey?.startsWith("agent:")) {
86836
+ return isValidOpenClawGatewaySessionKey(input.sessionKey) ? { sessionKeys: [input.sessionKey], source: "explicit_gateway_session" } : null;
86837
+ }
86838
+ return null;
86839
+ }
86840
+ async dispatchUserToGatewaySession(input, routed) {
86841
+ const gatewaySessionKey = routed.sessionKeys.join(",");
86842
+ console.error(
86843
+ `${GATEWAY_OUTBOUND_LOG_PREFIX} dispatchUser routed sessionKey=${input.sessionKey ?? "(none)"} gatewaySessionKey=${gatewaySessionKey} source=${routed.source} jobId=${input.jobId ?? "(none)"} idempotencyKey=${input.idempotencyKey ?? "(none)"}`
86844
+ );
86845
+ try {
86846
+ const result = await this.gateway.callDispatchUserToLatestSessions({
86847
+ content: input.userContent,
86848
+ label: "okx-a2a",
86849
+ ...routed.source === "stored_openclaw_routes" ? { sessionKeys: routed.sessionKeys } : { sessionKey: routed.sessionKeys[0] }
86850
+ });
86851
+ assertLatestUserFanoutDelivered("okx-a2a.dispatch_user", result);
86852
+ console.error(`${GATEWAY_OUTBOUND_LOG_PREFIX} dispatchUser routed ok gatewaySessionKey=${gatewaySessionKey} source=${routed.source}`);
86853
+ logger.info(LogEvent.USER_DISPATCHED, gatewayOutboundExtra("okx-a2a.dispatch_user", {
86854
+ sessionKey: input.sessionKey ?? "",
86855
+ gatewaySessionKey,
86856
+ jobId: input.jobId ?? "",
86857
+ source: routed.source,
86858
+ status: "delivered"
86859
+ }));
86860
+ } catch (err2) {
86861
+ if (!this.store || !isRetryableOpenClawGatewayError(err2)) {
86862
+ logger.error(LogEvent.USER_DISPATCH_FAILED, err2 instanceof Error ? err2 : new Error(String(err2)), gatewayOutboundExtra("okx-a2a.dispatch_user", {
86863
+ sessionKey: input.sessionKey ?? "",
86864
+ gatewaySessionKey,
86865
+ jobId: input.jobId ?? "",
86866
+ source: routed.source,
86867
+ status: "failed"
86868
+ }));
86869
+ throw err2;
86870
+ }
86871
+ this.store.enqueuePendingGatewayDelivery({
86872
+ kind: "chat_inject",
86873
+ provider: this.provider,
86874
+ sessionKey: routed.sessionKeys[0] ?? "openclaw:routed-user-sessions",
86875
+ content: input.userContent,
86876
+ jobId: input.jobId ?? null,
86877
+ messageId: input.idempotencyKey ?? null
86878
+ });
86879
+ console.error(
86880
+ `${GATEWAY_OUTBOUND_LOG_PREFIX} dispatchUser routed buffered gatewaySessionKey=${gatewaySessionKey} source=${routed.source} idempotencyKey=${input.idempotencyKey ?? "(none)"}: ${err2 instanceof Error ? err2.message : String(err2)}`
86881
+ );
86882
+ logger.error(LogEvent.USER_DISPATCH_FAILED, err2 instanceof Error ? err2 : new Error(String(err2)), gatewayOutboundExtra("okx-a2a.dispatch_user", {
86883
+ sessionKey: input.sessionKey ?? "",
86884
+ gatewaySessionKey,
86885
+ jobId: input.jobId ?? "",
86886
+ source: routed.source,
86887
+ status: "buffered"
86888
+ }));
86889
+ logger.info(LogEvent.GATEWAY_DELIVERY_BUFFERED, gatewayOutboundExtra("okx-a2a.dispatch_user", {
86890
+ sessionKey: input.sessionKey ?? "",
86891
+ gatewaySessionKey,
86892
+ jobId: input.jobId ?? "",
86893
+ messageId: input.idempotencyKey ?? "",
86894
+ source: routed.source,
86895
+ status: "buffered"
86896
+ }));
86897
+ }
86898
+ }
86495
86899
  async promptUser(input) {
86900
+ const routed = this.resolveUserGatewaySessionKey(input);
86901
+ if (routed) {
86902
+ await this.promptUserToGatewaySession(input, routed);
86903
+ return null;
86904
+ }
86496
86905
  errorWithTimestamp(
86497
86906
  `${GATEWAY_OUTBOUND_LOG_PREFIX} promptUser latestUserSessions jobId=${input.jobId ?? "(none)"} idempotencyKey=${input.idempotencyKey ?? "(none)"}`
86498
86907
  );
86499
86908
  try {
86500
86909
  const result = await this.gateway.callPromptUserToLatestSessions({
86501
86910
  userContent: input.userContent,
86502
- llmContent: input.llmContent
86911
+ llmContent: input.llmContent,
86912
+ ...input.jobId ? { jobId: input.jobId } : {},
86913
+ ...input.sessionKey ? { currentSessionKey: input.sessionKey } : {}
86503
86914
  });
86504
86915
  assertLatestUserFanoutDelivered("okx-a2a.prompt_user", result);
86505
86916
  errorWithTimestamp(`${GATEWAY_OUTBOUND_LOG_PREFIX} promptUser latestUserSessions ok`);
@@ -86539,6 +86950,66 @@ var GatewayOutboundBehavior = class {
86539
86950
  }
86540
86951
  return null;
86541
86952
  }
86953
+ async promptUserToGatewaySession(input, routed) {
86954
+ const gatewaySessionKey = routed.sessionKeys.join(",");
86955
+ console.error(
86956
+ `${GATEWAY_OUTBOUND_LOG_PREFIX} promptUser routed sessionKey=${input.sessionKey ?? "(none)"} gatewaySessionKey=${gatewaySessionKey} source=${routed.source} jobId=${input.jobId ?? "(none)"} idempotencyKey=${input.idempotencyKey ?? "(none)"}`
86957
+ );
86958
+ try {
86959
+ const result = await this.gateway.callPromptUserToLatestSessions({
86960
+ userContent: input.userContent,
86961
+ llmContent: input.llmContent,
86962
+ ...routed.source === "stored_openclaw_routes" ? { sessionKeys: routed.sessionKeys } : { sessionKey: routed.sessionKeys[0] }
86963
+ });
86964
+ assertLatestUserFanoutDelivered("okx-a2a.prompt_user", result);
86965
+ console.error(`${GATEWAY_OUTBOUND_LOG_PREFIX} promptUser routed ok gatewaySessionKey=${gatewaySessionKey} source=${routed.source}`);
86966
+ logger.info(LogEvent.PROMPT_USER_CHECKPOINT, gatewayOutboundExtra("routed_prompt_user", {
86967
+ sessionKey: input.sessionKey ?? "",
86968
+ gatewaySessionKey,
86969
+ jobId: input.jobId ?? "",
86970
+ source: routed.source,
86971
+ status: "delivered"
86972
+ }));
86973
+ } catch (err2) {
86974
+ if (!this.store || !isRetryableOpenClawGatewayError(err2)) {
86975
+ logger.error(LogEvent.PROMPT_USER_FAILED, err2 instanceof Error ? err2 : new Error(String(err2)), gatewayOutboundExtra("routed_prompt_user", {
86976
+ sessionKey: input.sessionKey ?? "",
86977
+ gatewaySessionKey,
86978
+ jobId: input.jobId ?? "",
86979
+ source: routed.source,
86980
+ status: "failed"
86981
+ }));
86982
+ throw err2;
86983
+ }
86984
+ this.store.enqueuePendingGatewayDelivery({
86985
+ kind: "chat_inject",
86986
+ provider: this.provider,
86987
+ sessionKey: routed.sessionKeys[0] ?? "openclaw:routed-user-sessions",
86988
+ content: input.userContent,
86989
+ llmContent: input.llmContent,
86990
+ jobId: input.jobId ?? null,
86991
+ messageId: input.idempotencyKey ?? null
86992
+ });
86993
+ console.error(
86994
+ `${GATEWAY_OUTBOUND_LOG_PREFIX} promptUser routed buffered gatewaySessionKey=${gatewaySessionKey} source=${routed.source} idempotencyKey=${input.idempotencyKey ?? "(none)"}: ${err2 instanceof Error ? err2.message : String(err2)}`
86995
+ );
86996
+ logger.error(LogEvent.PROMPT_USER_FAILED, err2 instanceof Error ? err2 : new Error(String(err2)), gatewayOutboundExtra("routed_prompt_user", {
86997
+ sessionKey: input.sessionKey ?? "",
86998
+ gatewaySessionKey,
86999
+ jobId: input.jobId ?? "",
87000
+ source: routed.source,
87001
+ status: "buffered"
87002
+ }));
87003
+ logger.info(LogEvent.GATEWAY_DELIVERY_BUFFERED, gatewayOutboundExtra("routed_prompt_user", {
87004
+ sessionKey: input.sessionKey ?? "",
87005
+ gatewaySessionKey,
87006
+ jobId: input.jobId ?? "",
87007
+ messageId: input.idempotencyKey ?? "",
87008
+ source: routed.source,
87009
+ status: "buffered"
87010
+ }));
87011
+ }
87012
+ }
86542
87013
  };
86543
87014
  function createOutboundBehavior(provider, deps) {
86544
87015
  if (provider === "openclaw") {
@@ -86627,15 +87098,27 @@ function resolveOutboundProvider(store, input) {
86627
87098
  if (input.override) {
86628
87099
  return input.override;
86629
87100
  }
87101
+ if (input.jobId && resolveOpenClawGatewayRoute(store, { jobId: input.jobId })) {
87102
+ return "openclaw";
87103
+ }
86630
87104
  try {
86631
- return resolveConfiguredAiProviderForJob({
87105
+ const configured = resolveConfiguredAiProviderForJob({
86632
87106
  store,
86633
87107
  jobId: input.jobId,
86634
87108
  env: process.env
86635
- }) ?? "codex";
87109
+ });
87110
+ if (configured) {
87111
+ return configured;
87112
+ }
86636
87113
  } catch {
86637
- return "codex";
86638
87114
  }
87115
+ if (readSyncedOpenClawGatewayConfig(store.homeDir)) {
87116
+ if (input.jobId?.trim()) {
87117
+ return store.bindJobProviderIfMissing({ jobId: input.jobId.trim(), provider: "openclaw" }).binding.provider;
87118
+ }
87119
+ return "openclaw";
87120
+ }
87121
+ return "codex";
86639
87122
  }
86640
87123
  async function notifyAgentMessageToUserAttention(input) {
86641
87124
  const ownedStore = input.store ? null : new SessionStore();
@@ -86767,6 +87250,9 @@ function bindOutboundJobProviderToCurrentDefault(sessionStore, jobId) {
86767
87250
  logWithTimestamp(`[okx-agent-task] job provider bind failed from outbound-xmtp: job=${jobId}`, err2);
86768
87251
  }
86769
87252
  }
87253
+ function bindOutboundOpenClawRouteIfCurrent(sessionStore, jobId, gatewaySessionKeys) {
87254
+ bindOpenClawGatewayRouteFromEnv(sessionStore, { jobId, gatewaySessionKeys });
87255
+ }
86770
87256
  function buildTaskPayload(replyToMessageId) {
86771
87257
  return {
86772
87258
  taskMinVersion: TASK_MIN_VERSION,
@@ -87203,6 +87689,7 @@ async function handleSqliteGroupSendCommand(params) {
87203
87689
  myAgentXmtpAddress: myXmtpAddress,
87204
87690
  toAgentXmtpAddress: remote.toXmtpAddress
87205
87691
  });
87692
+ bindOutboundOpenClawRouteIfCurrent(sessionStore, command.jobId, command.gatewaySessionKeys);
87206
87693
  return { conversation: conversation2, created: created2 };
87207
87694
  }
87208
87695
  );
@@ -87529,7 +88016,7 @@ async function handleXmtpSendCommand(params) {
87529
88016
  const sessionStore2 = params.sessionStore ?? ownedStore2;
87530
88017
  try {
87531
88018
  bindOutboundJobProviderToCurrentDefault(sessionStore2, command.jobId);
87532
- resolveConfiguredAiProviderForJob({ store: sessionStore2, jobId: command.jobId });
88019
+ bindOutboundOpenClawRouteIfCurrent(sessionStore2, command.jobId, command.gatewaySessionKeys);
87533
88020
  return await handleSqliteGroupSendCommand({
87534
88021
  command,
87535
88022
  service,
@@ -87543,7 +88030,7 @@ async function handleXmtpSendCommand(params) {
87543
88030
  const sessionStore = params.sessionStore ?? ownedStore;
87544
88031
  try {
87545
88032
  bindOutboundJobProviderToCurrentDefault(sessionStore, command.jobId);
87546
- resolveConfiguredAiProviderForJob({ store: sessionStore, jobId: command.jobId });
88033
+ bindOutboundOpenClawRouteIfCurrent(sessionStore, command.jobId, command.gatewaySessionKeys);
87547
88034
  const { file, sessionAgentId } = await readFileForSend({
87548
88035
  command,
87549
88036
  store,
@@ -89650,7 +90137,7 @@ function userWatchEventDeliveredSentryExtra(event) {
89650
90137
  var environment = process.env.SENTRY_ENV === "dev" ? "dev" : "prod";
89651
90138
  var SENTRY_CONFIG = {
89652
90139
  projectName: "okx/openclaw-okx-a2a-extension",
89653
- release: "0.0.15",
90140
+ release: "0.0.16-beta-d0ec14bc63-260623110312",
89654
90141
  environment
89655
90142
  };
89656
90143
 
@@ -89771,12 +90258,12 @@ async function runListenerWithLock(options, paths) {
89771
90258
  }));
89772
90259
  }
89773
90260
  });
89774
- service.setPluginVersion("0.0.15");
90261
+ service.setPluginVersion("0.0.16-beta-d0ec14bc63-260623110312");
89775
90262
  await service.init();
89776
90263
  const pluginVersionStatus = service.pluginVersionStatus;
89777
90264
  if (pluginVersionStatus.unavailable) {
89778
90265
  throw new Error(
89779
- `@okxweb3/a2a-node v${"0.0.15"} is below the required minimum v${pluginVersionStatus.minVersion}`
90266
+ `@okxweb3/a2a-node v${"0.0.16-beta-d0ec14bc63-260623110312"} is below the required minimum v${pluginVersionStatus.minVersion}`
89780
90267
  );
89781
90268
  }
89782
90269
  const systemConfig = service.getSystemConfig();
@@ -89794,7 +90281,7 @@ async function runListenerWithLock(options, paths) {
89794
90281
  onchainosAgentId: "*",
89795
90282
  reason: "system-config missing sentryDsn",
89796
90283
  pluginId: "@okxweb3/a2a-node",
89797
- pluginVersion: "0.0.15"
90284
+ pluginVersion: "0.0.16-beta-d0ec14bc63-260623110312"
89798
90285
  });
89799
90286
  }
89800
90287
  logWithTimestamp(
@@ -89963,8 +90450,8 @@ async function timeSettled(fn) {
89963
90450
 
89964
90451
  // src/update-cli.ts
89965
90452
  var import_promises6 = require("node:fs/promises");
89966
- var import_node_os5 = require("node:os");
89967
- var import_node_path17 = require("node:path");
90453
+ var import_node_os6 = require("node:os");
90454
+ var import_node_path18 = require("node:path");
89968
90455
  function isPrereleaseVersion(version2) {
89969
90456
  return /\d+\.\d+\.\d+-[0-9A-Za-z.-]+/.test(version2);
89970
90457
  }
@@ -90095,7 +90582,7 @@ function isEmptyInlineEnabledList(line) {
90095
90582
  return !!inline && inline.values.length === 0;
90096
90583
  }
90097
90584
  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");
90585
+ return (0, import_node_path18.join)(process.env.HERMES_HOME ?? (0, import_node_path18.join)((0, import_node_os6.homedir)(), ".hermes"), "config.yaml");
90099
90586
  }
90100
90587
  function lineIndent(line) {
90101
90588
  const match = line.match(/^\s*/);
@@ -90167,6 +90654,7 @@ function parsePluginYamlVersion(content3) {
90167
90654
  GatewayOutboundBehavior,
90168
90655
  InvalidXmtpMessageStore,
90169
90656
  OFFLINE_REPLAY_SYNC_INTERVAL,
90657
+ OPENCLAW_GATEWAY_ROUTE_GROUP_ID,
90170
90658
  SYSTEM_NOTIFICATION_SESSION_KEY,
90171
90659
  SessionStore,
90172
90660
  SqliteOutboundBehavior,
@@ -90180,6 +90668,7 @@ function parsePluginYamlVersion(content3) {
90180
90668
  bindJobProviderToCurrentDefaultIfMissing,
90181
90669
  bindJobProviderToCurrentRuntimeIfMissing,
90182
90670
  bindMessageJobProviderToCurrentDefault,
90671
+ bindOpenClawGatewayRouteFromEnv,
90183
90672
  buildAgentMessageNotice,
90184
90673
  buildAiAdapterCommand,
90185
90674
  buildAiProviderEnv,
@@ -90200,6 +90689,7 @@ function parsePluginYamlVersion(content3) {
90200
90689
  createFileMessageHandler,
90201
90690
  createOutboundBehavior,
90202
90691
  createUserAttentionWatchParentMonitor,
90692
+ currentOpenClawGatewaySessionKey,
90203
90693
  detectAiProviders,
90204
90694
  detectCurrentAiProvider,
90205
90695
  detectGatewayInvocation,
@@ -90233,6 +90723,8 @@ function parsePluginYamlVersion(content3) {
90233
90723
  resolveConfiguredAiProviderForJob,
90234
90724
  resolveDirectCommunicationSessionTarget,
90235
90725
  resolveOpenClawGatewayConfig,
90726
+ resolveOpenClawGatewayRoute,
90727
+ resolveOpenClawGatewayRoutes,
90236
90728
  resolveSystemNotificationTargets,
90237
90729
  resolveTaskConfigPath,
90238
90730
  resolveTaskHome,