@okxweb3/a2a-node 0.0.12 → 0.0.13-beta-d0ec14bc63-260622110355

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 +356 -21
  2. package/dist/index.js +328 -8
  3. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -3323,7 +3323,7 @@ var init_user_attention_ipc = __esm({
3323
3323
  function resolveOpenClawGatewayConfigPath(homeDir = resolveA2aTaskHome()) {
3324
3324
  return (0, import_node_path10.join)(homeDir, "openclaw-gateway.json");
3325
3325
  }
3326
- function readSyncedOpenClawGatewayConfig2(homeDir = resolveA2aTaskHome()) {
3326
+ function readSyncedOpenClawGatewayConfig(homeDir = resolveA2aTaskHome()) {
3327
3327
  const filePath = resolveOpenClawGatewayConfigPath(homeDir);
3328
3328
  if (!(0, import_node_fs7.existsSync)(filePath)) {
3329
3329
  return null;
@@ -7204,7 +7204,7 @@ async function sleep(ms) {
7204
7204
  }
7205
7205
  function readSyncedGatewayConfig(env) {
7206
7206
  try {
7207
- const synced = readSyncedOpenClawGatewayConfig2(env.OKX_AGENT_TASK_HOME);
7207
+ const synced = readSyncedOpenClawGatewayConfig(env.OKX_AGENT_TASK_HOME);
7208
7208
  if (!synced) {
7209
7209
  return null;
7210
7210
  }
@@ -7225,7 +7225,7 @@ function buildConnectParams(config, instanceId, protocolVersion) {
7225
7225
  client: {
7226
7226
  id: "gateway-client",
7227
7227
  displayName: "okx-a2a-node",
7228
- version: "0.0.12",
7228
+ version: "0.0.13-beta-d0ec14bc63-260622110355",
7229
7229
  platform: "node",
7230
7230
  mode: "backend",
7231
7231
  instanceId
@@ -7236,7 +7236,7 @@ function buildConnectParams(config, instanceId, protocolVersion) {
7236
7236
  commands: [],
7237
7237
  permissions: {},
7238
7238
  locale: Intl.DateTimeFormat().resolvedOptions().locale || "en-US",
7239
- userAgent: `okx-a2a-node/${"0.0.12"}`,
7239
+ userAgent: `okx-a2a-node/${"0.0.13-beta-d0ec14bc63-260622110355"}`,
7240
7240
  auth: {
7241
7241
  ...config.token ? { token: config.token } : {},
7242
7242
  ...config.password ? { password: config.password } : {}
@@ -7569,6 +7569,170 @@ var init_openclaw_session_key = __esm({
7569
7569
  }
7570
7570
  });
7571
7571
 
7572
+ // src/openclaw-route.ts
7573
+ function currentOpenClawGatewaySessionKey(env = process.env) {
7574
+ const candidate = currentOpenClawGatewaySessionCandidate(env);
7575
+ return candidate.ok ? candidate.sessionKey : null;
7576
+ }
7577
+ function currentOpenClawGatewaySessionCandidate(env = process.env) {
7578
+ const explicitGatewaySessionKey = normalizeText(env.OKX_A2A_CURRENT_GATEWAY_SESSION_KEY);
7579
+ if (explicitGatewaySessionKey) {
7580
+ return validateOpenClawGatewaySessionKey(explicitGatewaySessionKey);
7581
+ }
7582
+ const platform = normalizeText(env.OKX_A2A_CURRENT_GATEWAY_PLATFORM);
7583
+ const chatId = normalizeText(env.OKX_A2A_CURRENT_GATEWAY_CHAT_ID);
7584
+ const threadId = normalizeText(env.OKX_A2A_CURRENT_GATEWAY_THREAD_ID);
7585
+ if (platform && chatId) {
7586
+ return validateOpenClawGatewaySessionKey(
7587
+ deriveOpenClawGatewaySessionKey({ platform, chatId, threadId })
7588
+ );
7589
+ }
7590
+ const currentSessionKey = normalizeText(env.OKX_A2A_CURRENT_SESSION_KEY);
7591
+ if (currentSessionKey) {
7592
+ return validateOpenClawGatewaySessionKey(currentSessionKey);
7593
+ }
7594
+ return { ok: false, reason: "missing_gateway_session_key" };
7595
+ }
7596
+ function bindOpenClawGatewayRouteFromEnv(store, input, env = process.env) {
7597
+ const jobId = normalizeText(input.jobId);
7598
+ if (!jobId) {
7599
+ return null;
7600
+ }
7601
+ const existingRoute = findExistingValidOpenClawRoute(store, jobId);
7602
+ if (existingRoute) {
7603
+ return existingRoute.sessionKey;
7604
+ }
7605
+ const candidate = currentOpenClawGatewaySessionCandidate(env);
7606
+ if (!candidate.ok) {
7607
+ logOpenClawRouteSkip(candidate.reason, { jobId, sessionKey: candidate.sessionKey, existingRoute });
7608
+ return null;
7609
+ }
7610
+ const sessionKey = candidate.sessionKey;
7611
+ const routeSessionKey = buildOpenClawRouteSessionKey(jobId, sessionKey);
7612
+ pruneStaleOpenClawRoutes(store, jobId, routeSessionKey);
7613
+ store.upsertSession({
7614
+ sessionKey: routeSessionKey,
7615
+ jobId,
7616
+ myAgentId: sessionKey,
7617
+ groupId: OPENCLAW_GATEWAY_ROUTE_GROUP_ID
7618
+ });
7619
+ return sessionKey;
7620
+ }
7621
+ function resolveOpenClawGatewayRoute(store, input) {
7622
+ if (!store) {
7623
+ return null;
7624
+ }
7625
+ const jobId = normalizeText(input.jobId) ?? inferJobIdFromSessionKey(normalizeText(input.sessionKey));
7626
+ if (!jobId) {
7627
+ return null;
7628
+ }
7629
+ const route = store.querySessions({ jobId, limit: 25 }).find((session) => isOpenClawGatewayRoute(session));
7630
+ if (!route || !route.myAgentId) {
7631
+ return null;
7632
+ }
7633
+ return {
7634
+ sessionKey: route.myAgentId,
7635
+ jobId,
7636
+ routeSessionKey: route.sessionKey,
7637
+ updatedAt: route.updatedAt
7638
+ };
7639
+ }
7640
+ function isValidOpenClawGatewaySessionKey(sessionKey) {
7641
+ return validateOpenClawGatewaySessionKey(sessionKey).ok;
7642
+ }
7643
+ function buildOpenClawRouteSessionKey(jobId, gatewaySessionKey) {
7644
+ return [
7645
+ OPENCLAW_USER_SESSION_ROUTE_KEY_PREFIX,
7646
+ encodeURIComponent(jobId),
7647
+ encodeURIComponent(gatewaySessionKey)
7648
+ ].join(":");
7649
+ }
7650
+ function isOpenClawGatewayRoute(session) {
7651
+ return session.groupId === OPENCLAW_GATEWAY_ROUTE_GROUP_ID && validateOpenClawGatewaySessionKey(session.myAgentId).ok;
7652
+ }
7653
+ function findExistingValidOpenClawRoute(store, jobId) {
7654
+ return resolveOpenClawGatewayRoute(store, { jobId });
7655
+ }
7656
+ function pruneStaleOpenClawRoutes(store, jobId, keepRouteSessionKey) {
7657
+ if (!store.deleteSession) {
7658
+ return;
7659
+ }
7660
+ for (const session of store.querySessions({ jobId, limit: 100 })) {
7661
+ if (session.groupId === OPENCLAW_GATEWAY_ROUTE_GROUP_ID && session.sessionKey !== keepRouteSessionKey) {
7662
+ store.deleteSession(session.sessionKey);
7663
+ }
7664
+ }
7665
+ }
7666
+ function validateOpenClawGatewaySessionKey(sessionKey) {
7667
+ const key = normalizeText(sessionKey);
7668
+ if (!key) {
7669
+ return { ok: false, reason: "missing_gateway_session_key" };
7670
+ }
7671
+ if (key.startsWith("backup:")) {
7672
+ return { ok: false, reason: "internal_gateway_session_key", sessionKey: key };
7673
+ }
7674
+ if (key === "agent:main") {
7675
+ return { ok: true, sessionKey: key };
7676
+ }
7677
+ const parts = key.split(":");
7678
+ if (parts.length < 4 || parts[0] !== "agent" || !parts[1]) {
7679
+ return { ok: false, reason: "invalid_gateway_session_key", sessionKey: key };
7680
+ }
7681
+ const platform = parts[2];
7682
+ if (!platform || platform === "okx-a2a") {
7683
+ return { ok: false, reason: "internal_gateway_session_key", sessionKey: key };
7684
+ }
7685
+ return { ok: true, sessionKey: key };
7686
+ }
7687
+ function deriveOpenClawGatewaySessionKey(input) {
7688
+ const chatId = encodeURIComponent(input.chatId);
7689
+ const threadId = input.threadId ? encodeURIComponent(input.threadId) : "";
7690
+ if (input.platform === "telegram") {
7691
+ return threadId ? `agent:main:telegram:group:${chatId}:topic:${threadId}` : `agent:main:telegram:direct:${chatId}`;
7692
+ }
7693
+ return threadId ? `agent:main:${input.platform}:thread:${chatId}:${threadId}` : `agent:main:${input.platform}:dm:${chatId}`;
7694
+ }
7695
+ function logOpenClawRouteSkip(reason, input) {
7696
+ if (reason === "missing_gateway_session_key") {
7697
+ return;
7698
+ }
7699
+ console.error(
7700
+ `[openclaw-route] skipped gateway route bind reason=${reason} jobId=${input.jobId} sessionKey=${input.sessionKey ?? "(none)"} existingRoute=${input.existingRoute?.sessionKey ?? "(none)"}`
7701
+ );
7702
+ }
7703
+ function inferJobIdFromSessionKey(sessionKey) {
7704
+ if (!sessionKey) {
7705
+ return null;
7706
+ }
7707
+ const parts = sessionKey.split(":");
7708
+ if (parts.length >= 2 && parts[0] === "job") {
7709
+ return safeDecode2(parts[1]);
7710
+ }
7711
+ if (sessionKey.startsWith("backup:")) {
7712
+ return safeDecode2(sessionKey.slice("backup:".length));
7713
+ }
7714
+ return null;
7715
+ }
7716
+ function normalizeText(value) {
7717
+ const text = value?.trim();
7718
+ return text ? text : null;
7719
+ }
7720
+ function safeDecode2(value) {
7721
+ try {
7722
+ return decodeURIComponent(value);
7723
+ } catch {
7724
+ return value;
7725
+ }
7726
+ }
7727
+ var OPENCLAW_GATEWAY_ROUTE_GROUP_ID, OPENCLAW_USER_SESSION_ROUTE_KEY_PREFIX;
7728
+ var init_openclaw_route = __esm({
7729
+ "src/openclaw-route.ts"() {
7730
+ "use strict";
7731
+ OPENCLAW_GATEWAY_ROUTE_GROUP_ID = "__openclaw_gateway_route__";
7732
+ OPENCLAW_USER_SESSION_ROUTE_KEY_PREFIX = "user-session-route:openclaw";
7733
+ }
7734
+ });
7735
+
7572
7736
  // ../../node_modules/@sentry/utils/cjs/is.js
7573
7737
  var require_is = __commonJS({
7574
7738
  "../../node_modules/@sentry/utils/cjs/is.js"(exports2) {
@@ -23365,6 +23529,7 @@ var init_outbound_behavior = __esm({
23365
23529
  init_user_attention_ipc();
23366
23530
  init_openclaw_gateway();
23367
23531
  init_openclaw_session_key();
23532
+ init_openclaw_route();
23368
23533
  init_sentry_logger();
23369
23534
  SqliteOutboundBehavior = class {
23370
23535
  provider;
@@ -23562,6 +23727,11 @@ var init_outbound_behavior = __esm({
23562
23727
  });
23563
23728
  }
23564
23729
  async dispatchUser(input) {
23730
+ const routed = this.resolveUserGatewaySessionKey(input);
23731
+ if (routed) {
23732
+ await this.dispatchUserToGatewaySession(input, routed);
23733
+ return null;
23734
+ }
23565
23735
  console.error(
23566
23736
  `${GATEWAY_OUTBOUND_LOG_PREFIX} dispatchUser latestUserSessions jobId=${input.jobId ?? "(none)"} idempotencyKey=${input.idempotencyKey ?? "(none)"}`
23567
23737
  );
@@ -23604,7 +23774,85 @@ var init_outbound_behavior = __esm({
23604
23774
  }
23605
23775
  return null;
23606
23776
  }
23777
+ resolveUserGatewaySessionKey(input) {
23778
+ const route = resolveOpenClawGatewayRoute(this.sessionMetaStore, input);
23779
+ if (route) {
23780
+ return { sessionKey: route.sessionKey, source: "stored_openclaw_route" };
23781
+ }
23782
+ if (input.sessionKey?.startsWith("agent:")) {
23783
+ return isValidOpenClawGatewaySessionKey(input.sessionKey) ? { sessionKey: input.sessionKey, source: "explicit_gateway_session" } : null;
23784
+ }
23785
+ if (input.sessionKey) {
23786
+ return {
23787
+ sessionKey: this.resolveGatewaySessionKey({ ...input, sessionKey: input.sessionKey }),
23788
+ source: "derived_a2a_session"
23789
+ };
23790
+ }
23791
+ return null;
23792
+ }
23793
+ async dispatchUserToGatewaySession(input, routed) {
23794
+ console.error(
23795
+ `${GATEWAY_OUTBOUND_LOG_PREFIX} dispatchUser chatInject sessionKey=${input.sessionKey ?? "(none)"} gatewaySessionKey=${routed.sessionKey} source=${routed.source} jobId=${input.jobId ?? "(none)"} idempotencyKey=${input.idempotencyKey ?? "(none)"}`
23796
+ );
23797
+ try {
23798
+ await this.gateway.callChatInject({
23799
+ sessionKey: routed.sessionKey,
23800
+ message: input.userContent,
23801
+ label: "okx-a2a"
23802
+ });
23803
+ console.error(`${GATEWAY_OUTBOUND_LOG_PREFIX} dispatchUser chatInject ok gatewaySessionKey=${routed.sessionKey} source=${routed.source}`);
23804
+ logger.info(LogEvent.USER_DISPATCHED, gatewayOutboundExtra("chat.inject", {
23805
+ sessionKey: input.sessionKey ?? "",
23806
+ gatewaySessionKey: routed.sessionKey,
23807
+ jobId: input.jobId ?? "",
23808
+ source: routed.source,
23809
+ status: "delivered"
23810
+ }));
23811
+ } catch (err2) {
23812
+ if (!this.store || !isRetryableOpenClawGatewayError(err2)) {
23813
+ logger.error(LogEvent.USER_DISPATCH_FAILED, err2 instanceof Error ? err2 : new Error(String(err2)), gatewayOutboundExtra("chat.inject", {
23814
+ sessionKey: input.sessionKey ?? "",
23815
+ gatewaySessionKey: routed.sessionKey,
23816
+ jobId: input.jobId ?? "",
23817
+ source: routed.source,
23818
+ status: "failed"
23819
+ }));
23820
+ throw err2;
23821
+ }
23822
+ this.store.enqueuePendingGatewayDelivery({
23823
+ kind: "chat_inject",
23824
+ provider: this.provider,
23825
+ sessionKey: routed.sessionKey,
23826
+ content: input.userContent,
23827
+ jobId: input.jobId ?? null,
23828
+ messageId: input.idempotencyKey ?? null
23829
+ });
23830
+ console.error(
23831
+ `${GATEWAY_OUTBOUND_LOG_PREFIX} dispatchUser chatInject buffered gatewaySessionKey=${routed.sessionKey} source=${routed.source} idempotencyKey=${input.idempotencyKey ?? "(none)"}: ${err2 instanceof Error ? err2.message : String(err2)}`
23832
+ );
23833
+ logger.error(LogEvent.USER_DISPATCH_FAILED, err2 instanceof Error ? err2 : new Error(String(err2)), gatewayOutboundExtra("chat.inject", {
23834
+ sessionKey: input.sessionKey ?? "",
23835
+ gatewaySessionKey: routed.sessionKey,
23836
+ jobId: input.jobId ?? "",
23837
+ source: routed.source,
23838
+ status: "buffered"
23839
+ }));
23840
+ logger.info(LogEvent.GATEWAY_DELIVERY_BUFFERED, gatewayOutboundExtra("chat.inject", {
23841
+ sessionKey: input.sessionKey ?? "",
23842
+ gatewaySessionKey: routed.sessionKey,
23843
+ jobId: input.jobId ?? "",
23844
+ messageId: input.idempotencyKey ?? "",
23845
+ source: routed.source,
23846
+ status: "buffered"
23847
+ }));
23848
+ }
23849
+ }
23607
23850
  async promptUser(input) {
23851
+ const routed = this.resolveUserGatewaySessionKey(input);
23852
+ if (routed) {
23853
+ await this.promptUserToGatewaySession(input, routed);
23854
+ return null;
23855
+ }
23608
23856
  console.error(
23609
23857
  `${GATEWAY_OUTBOUND_LOG_PREFIX} promptUser latestUserSessions jobId=${input.jobId ?? "(none)"} idempotencyKey=${input.idempotencyKey ?? "(none)"}`
23610
23858
  );
@@ -23651,6 +23899,71 @@ var init_outbound_behavior = __esm({
23651
23899
  }
23652
23900
  return null;
23653
23901
  }
23902
+ async promptUserToGatewaySession(input, routed) {
23903
+ console.error(
23904
+ `${GATEWAY_OUTBOUND_LOG_PREFIX} promptUser routed sessionKey=${input.sessionKey ?? "(none)"} gatewaySessionKey=${routed.sessionKey} source=${routed.source} jobId=${input.jobId ?? "(none)"} idempotencyKey=${input.idempotencyKey ?? "(none)"}`
23905
+ );
23906
+ let llmSent = false;
23907
+ try {
23908
+ await this.gateway.callSessionsSend({
23909
+ key: routed.sessionKey,
23910
+ message: input.llmContent,
23911
+ ...input.idempotencyKey ? { idempotencyKey: input.idempotencyKey } : {}
23912
+ });
23913
+ llmSent = true;
23914
+ await this.gateway.callChatInject({
23915
+ sessionKey: routed.sessionKey,
23916
+ message: input.userContent,
23917
+ label: "okx-a2a"
23918
+ });
23919
+ console.error(`${GATEWAY_OUTBOUND_LOG_PREFIX} promptUser routed ok gatewaySessionKey=${routed.sessionKey} source=${routed.source}`);
23920
+ logger.info(LogEvent.PROMPT_USER_CHECKPOINT, gatewayOutboundExtra("routed_prompt_user", {
23921
+ sessionKey: input.sessionKey ?? "",
23922
+ gatewaySessionKey: routed.sessionKey,
23923
+ jobId: input.jobId ?? "",
23924
+ source: routed.source,
23925
+ status: "delivered"
23926
+ }));
23927
+ } catch (err2) {
23928
+ if (!this.store || !isRetryableOpenClawGatewayError(err2)) {
23929
+ logger.error(LogEvent.PROMPT_USER_FAILED, err2 instanceof Error ? err2 : new Error(String(err2)), gatewayOutboundExtra("routed_prompt_user", {
23930
+ sessionKey: input.sessionKey ?? "",
23931
+ gatewaySessionKey: routed.sessionKey,
23932
+ jobId: input.jobId ?? "",
23933
+ source: routed.source,
23934
+ status: "failed"
23935
+ }));
23936
+ throw err2;
23937
+ }
23938
+ this.store.enqueuePendingGatewayDelivery({
23939
+ kind: "chat_inject",
23940
+ provider: this.provider,
23941
+ sessionKey: routed.sessionKey,
23942
+ content: input.userContent,
23943
+ llmContent: llmSent ? null : input.llmContent,
23944
+ jobId: input.jobId ?? null,
23945
+ messageId: input.idempotencyKey ?? null
23946
+ });
23947
+ console.error(
23948
+ `${GATEWAY_OUTBOUND_LOG_PREFIX} promptUser routed buffered gatewaySessionKey=${routed.sessionKey} source=${routed.source} llmSent=${llmSent ? 1 : 0} idempotencyKey=${input.idempotencyKey ?? "(none)"}: ${err2 instanceof Error ? err2.message : String(err2)}`
23949
+ );
23950
+ logger.error(LogEvent.PROMPT_USER_FAILED, err2 instanceof Error ? err2 : new Error(String(err2)), gatewayOutboundExtra("routed_prompt_user", {
23951
+ sessionKey: input.sessionKey ?? "",
23952
+ gatewaySessionKey: routed.sessionKey,
23953
+ jobId: input.jobId ?? "",
23954
+ source: routed.source,
23955
+ status: "buffered"
23956
+ }));
23957
+ logger.info(LogEvent.GATEWAY_DELIVERY_BUFFERED, gatewayOutboundExtra("routed_prompt_user", {
23958
+ sessionKey: input.sessionKey ?? "",
23959
+ gatewaySessionKey: routed.sessionKey,
23960
+ jobId: input.jobId ?? "",
23961
+ messageId: input.idempotencyKey ?? "",
23962
+ source: routed.source,
23963
+ status: "buffered"
23964
+ }));
23965
+ }
23966
+ }
23654
23967
  };
23655
23968
  }
23656
23969
  });
@@ -23777,7 +24090,7 @@ var init_sentry_config = __esm({
23777
24090
  environment = process.env.SENTRY_ENV === "dev" ? "dev" : "prod";
23778
24091
  SENTRY_CONFIG = {
23779
24092
  projectName: "okx/openclaw-okx-a2a-extension",
23780
- release: "0.0.12",
24093
+ release: "0.0.13-beta-d0ec14bc63-260622110355",
23781
24094
  environment
23782
24095
  };
23783
24096
  }
@@ -85328,6 +85641,12 @@ function bindOutboundJobProviderToCurrentDefault(sessionStore, jobId) {
85328
85641
  console.log(`[okx-agent-task] job provider bind failed from outbound-xmtp: job=${jobId}`, err2);
85329
85642
  }
85330
85643
  }
85644
+ function bindOutboundOpenClawRouteIfCurrent(sessionStore, jobId) {
85645
+ const provider = resolveConfiguredAiProviderForJob({ store: sessionStore, jobId });
85646
+ if (provider === "openclaw") {
85647
+ bindOpenClawGatewayRouteFromEnv(sessionStore, { jobId });
85648
+ }
85649
+ }
85331
85650
  function buildTaskPayload(replyToMessageId) {
85332
85651
  return {
85333
85652
  taskMinVersion: TASK_MIN_VERSION,
@@ -86088,7 +86407,7 @@ async function handleXmtpSendCommand(params) {
86088
86407
  const sessionStore2 = params.sessionStore ?? ownedStore2;
86089
86408
  try {
86090
86409
  bindOutboundJobProviderToCurrentDefault(sessionStore2, command.jobId);
86091
- resolveConfiguredAiProviderForJob({ store: sessionStore2, jobId: command.jobId });
86410
+ bindOutboundOpenClawRouteIfCurrent(sessionStore2, command.jobId);
86092
86411
  return await handleSqliteGroupSendCommand({
86093
86412
  command,
86094
86413
  service,
@@ -86102,7 +86421,7 @@ async function handleXmtpSendCommand(params) {
86102
86421
  const sessionStore = params.sessionStore ?? ownedStore;
86103
86422
  try {
86104
86423
  bindOutboundJobProviderToCurrentDefault(sessionStore, command.jobId);
86105
- resolveConfiguredAiProviderForJob({ store: sessionStore, jobId: command.jobId });
86424
+ bindOutboundOpenClawRouteIfCurrent(sessionStore, command.jobId);
86106
86425
  const { file, sessionAgentId } = await readFileForSend({
86107
86426
  command,
86108
86427
  store,
@@ -86193,6 +86512,7 @@ var init_xmtp_send = __esm({
86193
86512
  init_session_store();
86194
86513
  init_ai_provider();
86195
86514
  init_agent_message_notice();
86515
+ init_openclaw_route();
86196
86516
  TASK_MIN_VERSION = 1;
86197
86517
  sqliteGroupSessionPromises = /* @__PURE__ */ new Map();
86198
86518
  resolvedAgentByIdCache = /* @__PURE__ */ new Map();
@@ -87221,7 +87541,7 @@ function parseSessionKeyDetails(sessionKey) {
87221
87541
  kind: sessionKey || "unknown"
87222
87542
  };
87223
87543
  }
87224
- function inferJobIdFromSessionKey(sessionKey) {
87544
+ function inferJobIdFromSessionKey2(sessionKey) {
87225
87545
  const jobPrefixMatch = /^job:([^:]+):/.exec(sessionKey);
87226
87546
  if (jobPrefixMatch?.[1]) {
87227
87547
  return normalizeOptionalText(safeDecodeURIComponent(jobPrefixMatch[1]));
@@ -88004,7 +88324,7 @@ var init_ai_runner = __esm({
88004
88324
  if (sessionJobId) {
88005
88325
  return sessionJobId;
88006
88326
  }
88007
- return inferJobIdFromSessionKey(request.sessionKey);
88327
+ return inferJobIdFromSessionKey2(request.sessionKey);
88008
88328
  }
88009
88329
  buildRunQueueKey(request) {
88010
88330
  if (request.source === "job-dispatch") {
@@ -90740,12 +91060,12 @@ async function runListenerWithLock(options, paths) {
90740
91060
  }));
90741
91061
  }
90742
91062
  });
90743
- service.setPluginVersion("0.0.12");
91063
+ service.setPluginVersion("0.0.13-beta-d0ec14bc63-260622110355");
90744
91064
  await service.init();
90745
91065
  const pluginVersionStatus = service.pluginVersionStatus;
90746
91066
  if (pluginVersionStatus.unavailable) {
90747
91067
  throw new Error(
90748
- `@okxweb3/a2a-node v${"0.0.12"} is below the required minimum v${pluginVersionStatus.minVersion}`
91068
+ `@okxweb3/a2a-node v${"0.0.13-beta-d0ec14bc63-260622110355"} is below the required minimum v${pluginVersionStatus.minVersion}`
90749
91069
  );
90750
91070
  }
90751
91071
  const systemConfig = service.getSystemConfig();
@@ -90763,7 +91083,7 @@ async function runListenerWithLock(options, paths) {
90763
91083
  onchainosAgentId: "*",
90764
91084
  reason: "system-config missing sentryDsn",
90765
91085
  pluginId: "@okxweb3/a2a-node",
90766
- pluginVersion: "0.0.12"
91086
+ pluginVersion: "0.0.13-beta-d0ec14bc63-260622110355"
90767
91087
  });
90768
91088
  }
90769
91089
  console.log(
@@ -91415,6 +91735,7 @@ async function handleUserCommand(args) {
91415
91735
  const sessionKey = readCurrentSessionKeyFromEnv();
91416
91736
  await runWithoutConsoleOutput(async () => {
91417
91737
  bindHermesAttentionRouteIfAvailable({ provider, jobId, sessionKey });
91738
+ bindOpenClawAttentionRouteIfAvailable({ store, provider, jobId });
91418
91739
  await behavior.dispatchUser({
91419
91740
  userContent: readRequiredOption2(parsed, "content"),
91420
91741
  jobId,
@@ -91435,6 +91756,7 @@ async function handleUserCommand(args) {
91435
91756
  const sessionKey = readCurrentSessionKeyFromEnv();
91436
91757
  await runWithoutConsoleOutput(async () => {
91437
91758
  bindHermesAttentionRouteIfAvailable({ provider, jobId, sessionKey });
91759
+ bindOpenClawAttentionRouteIfAvailable({ store, provider, jobId });
91438
91760
  await behavior.promptUser({
91439
91761
  userContent: readRequiredOption2(parsed, "user-content"),
91440
91762
  llmContent: readRequiredOption2(parsed, "llm-content"),
@@ -91873,7 +92195,7 @@ function readJobId(parsed) {
91873
92195
  return envJobId;
91874
92196
  }
91875
92197
  const sessionKey = readCurrentSessionKeyFromEnv();
91876
- return sessionKey ? inferJobIdFromSessionKey2(sessionKey) : null;
92198
+ return sessionKey ? inferJobIdFromSessionKey3(sessionKey) : null;
91877
92199
  }
91878
92200
  function assertNoUserSessionKey(parsed, subcommand) {
91879
92201
  if (parsed.options.has("session-key")) {
@@ -91918,7 +92240,7 @@ function resolveUserAttentionProvider(store, jobId) {
91918
92240
  if (boundOrConfigured) {
91919
92241
  return boundOrConfigured;
91920
92242
  }
91921
- if (readSyncedOpenClawGatewayConfig2(store.homeDir)) {
92243
+ if (readSyncedOpenClawGatewayConfig(store.homeDir)) {
91922
92244
  if (jobId?.trim()) {
91923
92245
  return store.bindJobProviderIfMissing({ jobId: jobId.trim(), provider: "openclaw" }).binding.provider;
91924
92246
  }
@@ -91978,6 +92300,12 @@ function bindHermesAttentionRouteIfAvailable(input) {
91978
92300
  threadId: route.thread_id
91979
92301
  });
91980
92302
  }
92303
+ function bindOpenClawAttentionRouteIfAvailable(input) {
92304
+ if (input.provider !== "openclaw") {
92305
+ return;
92306
+ }
92307
+ bindOpenClawGatewayRouteFromEnv(input.store, { jobId: input.jobId });
92308
+ }
91981
92309
  function currentHermesRouteFromEnv() {
91982
92310
  const platform = normalizeOptionalText2(process.env.OKX_A2A_CURRENT_GATEWAY_PLATFORM);
91983
92311
  const chatId = normalizeOptionalText2(process.env.OKX_A2A_CURRENT_GATEWAY_CHAT_ID);
@@ -92071,7 +92399,7 @@ function isHermesRouteBindingDebugEnabled() {
92071
92399
  function isRecord2(value) {
92072
92400
  return !!value && typeof value === "object" && !Array.isArray(value);
92073
92401
  }
92074
- function inferJobIdFromSessionKey2(sessionKey) {
92402
+ function inferJobIdFromSessionKey3(sessionKey) {
92075
92403
  const jobPrefix = /^job:([^:]+):/.exec(sessionKey);
92076
92404
  if (jobPrefix?.[1]) {
92077
92405
  return normalizeOptionalText2(safeDecodeURIComponent2(jobPrefix[1]));
@@ -92119,6 +92447,7 @@ var init_user_attention_cli = __esm({
92119
92447
  init_user_attention_ipc();
92120
92448
  init_ai_provider();
92121
92449
  init_outbound_behavior();
92450
+ init_openclaw_route();
92122
92451
  init_openclaw_gateway();
92123
92452
  init_paths();
92124
92453
  init_openclaw_gateway_config();
@@ -92165,6 +92494,7 @@ async function handleSessionCommand(args) {
92165
92494
  const provider = resolveSessionLifecycleProvider(store, input.jobId);
92166
92495
  if (provider === "openclaw") {
92167
92496
  usedOpenClawGateway = true;
92497
+ bindOpenClawGatewayRouteFromEnv(store, { jobId: input.jobId });
92168
92498
  await createOutboundBehavior(provider, { store }).createSession({
92169
92499
  sessionKey: input.sessionKey,
92170
92500
  jobId: input.jobId,
@@ -92232,7 +92562,7 @@ async function handleSessionCommand(args) {
92232
92562
  const exactExisting = exactSessionKey ? store.getSession(exactSessionKey) : null;
92233
92563
  const provider = resolveSessionDeleteProvider(
92234
92564
  store,
92235
- exactExisting?.jobId ?? (exactSessionKey ? inferJobIdFromSessionKey3(exactSessionKey) : jobId)
92565
+ exactExisting?.jobId ?? (exactSessionKey ? inferJobIdFromSessionKey4(exactSessionKey) : jobId)
92236
92566
  );
92237
92567
  if (provider === "openclaw") {
92238
92568
  usedOpenClawGateway = true;
@@ -92925,7 +93255,7 @@ function resolveSendSessionTargets(parsed, store) {
92925
93255
  if (sessionKey) {
92926
93256
  return [{
92927
93257
  sessionKey,
92928
- jobId: parsed.options.get("job-id") ?? inferJobIdFromSessionKey3(sessionKey),
93258
+ jobId: parsed.options.get("job-id") ?? inferJobIdFromSessionKey4(sessionKey),
92929
93259
  agentId: parsed.options.get("agent-id") ?? parsed.options.get("my-agent-id") ?? null,
92930
93260
  toAgentId: null
92931
93261
  }];
@@ -93006,7 +93336,7 @@ function parseModernSessionKey(sessionKey) {
93006
93336
  toAgentId: decodeURIComponent(parts[5])
93007
93337
  };
93008
93338
  }
93009
- function inferJobIdFromSessionKey3(sessionKey) {
93339
+ function inferJobIdFromSessionKey4(sessionKey) {
93010
93340
  const modern = parseModernSessionKey(sessionKey);
93011
93341
  if (modern?.jobId) {
93012
93342
  return modern.jobId;
@@ -93100,9 +93430,11 @@ var init_session_cli = __esm({
93100
93430
  init_ai_dispatch_queue();
93101
93431
  init_ai_provider();
93102
93432
  init_outbound_behavior();
93433
+ init_openclaw_route();
93103
93434
  init_openclaw_gateway();
93104
93435
  init_sentry_logger();
93105
93436
  init_paths();
93437
+ init_openclaw_gateway_config();
93106
93438
  }
93107
93439
  });
93108
93440
 
@@ -93610,7 +93942,7 @@ function isPrereleaseVersion(version2) {
93610
93942
  }
93611
93943
  function getCurrentNodeCliVersion() {
93612
93944
  try {
93613
- return "0.0.12";
93945
+ return "0.0.13-beta-d0ec14bc63-260622110355";
93614
93946
  } catch {
93615
93947
  return null;
93616
93948
  }
@@ -94068,12 +94400,13 @@ init_file_store();
94068
94400
  init_ai_provider();
94069
94401
  init_session_store();
94070
94402
  init_outbound_behavior();
94403
+ init_openclaw_route();
94071
94404
  init_paths();
94072
94405
  init_task_config();
94073
94406
  init_sentry_logger();
94074
94407
  init_sentry_config();
94075
94408
  function printUsage2() {
94076
- console.log(`okx-a2a ${"0.0.12"}
94409
+ console.log(`okx-a2a ${"0.0.13-beta-d0ec14bc63-260622110355"}
94077
94410
 
94078
94411
  Usage:
94079
94412
  okx-a2a <command> [options]
@@ -94110,7 +94443,7 @@ Run \`okx-a2a <command> -h\` for command-specific help.
94110
94443
  `);
94111
94444
  }
94112
94445
  function printVersion() {
94113
- console.log("0.0.12");
94446
+ console.log("0.0.13-beta-d0ec14bc63-260622110355");
94114
94447
  }
94115
94448
  function printDaemonUsage() {
94116
94449
  console.log(`Usage: okx-a2a daemon <start|restart|stop|status> [options]
@@ -94784,8 +95117,10 @@ async function dispatchRuntimeSwitchUserMessage(store, result) {
94784
95117
  return;
94785
95118
  }
94786
95119
  try {
95120
+ const sessionKey = result.provider === "openclaw" ? currentOpenClawGatewaySessionKey() ?? void 0 : void 0;
94787
95121
  await createOutboundBehavior(result.provider, { store }).dispatchUser({
94788
95122
  userContent: result.userMessage,
95123
+ ...sessionKey ? { sessionKey } : {},
94789
95124
  idempotencyKey: `runtime-switch:${result.provider}:${result.previousProvider ?? "none"}`
94790
95125
  });
94791
95126
  } catch (err2) {
package/dist/index.js CHANGED
@@ -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,7 @@ __export(index_exports, {
67998
68001
  resolveConfiguredAiProviderForJob: () => resolveConfiguredAiProviderForJob,
67999
68002
  resolveDirectCommunicationSessionTarget: () => resolveDirectCommunicationSessionTarget,
68000
68003
  resolveOpenClawGatewayConfig: () => resolveOpenClawGatewayConfig,
68004
+ resolveOpenClawGatewayRoute: () => resolveOpenClawGatewayRoute,
68001
68005
  resolveSystemNotificationTargets: () => resolveSystemNotificationTargets,
68002
68006
  resolveTaskConfigPath: () => resolveTaskConfigPath,
68003
68007
  resolveTaskHome: () => resolveTaskHome,
@@ -85891,7 +85895,7 @@ function buildConnectParams(config, instanceId, protocolVersion) {
85891
85895
  client: {
85892
85896
  id: "gateway-client",
85893
85897
  displayName: "okx-a2a-node",
85894
- version: "0.0.12",
85898
+ version: "0.0.13-beta-d0ec14bc63-260622110355",
85895
85899
  platform: "node",
85896
85900
  mode: "backend",
85897
85901
  instanceId
@@ -85902,7 +85906,7 @@ function buildConnectParams(config, instanceId, protocolVersion) {
85902
85906
  commands: [],
85903
85907
  permissions: {},
85904
85908
  locale: Intl.DateTimeFormat().resolvedOptions().locale || "en-US",
85905
- userAgent: `okx-a2a-node/${"0.0.12"}`,
85909
+ userAgent: `okx-a2a-node/${"0.0.13-beta-d0ec14bc63-260622110355"}`,
85906
85910
  auth: {
85907
85911
  ...config.token ? { token: config.token } : {},
85908
85912
  ...config.password ? { password: config.password } : {}
@@ -86027,6 +86031,164 @@ function safeDecode(value) {
86027
86031
  }
86028
86032
  }
86029
86033
 
86034
+ // src/openclaw-route.ts
86035
+ var OPENCLAW_GATEWAY_ROUTE_GROUP_ID = "__openclaw_gateway_route__";
86036
+ var OPENCLAW_USER_SESSION_ROUTE_KEY_PREFIX = "user-session-route:openclaw";
86037
+ function currentOpenClawGatewaySessionKey(env = process.env) {
86038
+ const candidate = currentOpenClawGatewaySessionCandidate(env);
86039
+ return candidate.ok ? candidate.sessionKey : null;
86040
+ }
86041
+ function currentOpenClawGatewaySessionCandidate(env = process.env) {
86042
+ const explicitGatewaySessionKey = normalizeText(env.OKX_A2A_CURRENT_GATEWAY_SESSION_KEY);
86043
+ if (explicitGatewaySessionKey) {
86044
+ return validateOpenClawGatewaySessionKey(explicitGatewaySessionKey);
86045
+ }
86046
+ const platform = normalizeText(env.OKX_A2A_CURRENT_GATEWAY_PLATFORM);
86047
+ const chatId = normalizeText(env.OKX_A2A_CURRENT_GATEWAY_CHAT_ID);
86048
+ const threadId = normalizeText(env.OKX_A2A_CURRENT_GATEWAY_THREAD_ID);
86049
+ if (platform && chatId) {
86050
+ return validateOpenClawGatewaySessionKey(
86051
+ deriveOpenClawGatewaySessionKey({ platform, chatId, threadId })
86052
+ );
86053
+ }
86054
+ const currentSessionKey = normalizeText(env.OKX_A2A_CURRENT_SESSION_KEY);
86055
+ if (currentSessionKey) {
86056
+ return validateOpenClawGatewaySessionKey(currentSessionKey);
86057
+ }
86058
+ return { ok: false, reason: "missing_gateway_session_key" };
86059
+ }
86060
+ function bindOpenClawGatewayRouteFromEnv(store, input, env = process.env) {
86061
+ const jobId = normalizeText(input.jobId);
86062
+ if (!jobId) {
86063
+ return null;
86064
+ }
86065
+ const existingRoute = findExistingValidOpenClawRoute(store, jobId);
86066
+ if (existingRoute) {
86067
+ return existingRoute.sessionKey;
86068
+ }
86069
+ const candidate = currentOpenClawGatewaySessionCandidate(env);
86070
+ if (!candidate.ok) {
86071
+ logOpenClawRouteSkip(candidate.reason, { jobId, sessionKey: candidate.sessionKey, existingRoute });
86072
+ return null;
86073
+ }
86074
+ const sessionKey = candidate.sessionKey;
86075
+ const routeSessionKey = buildOpenClawRouteSessionKey(jobId, sessionKey);
86076
+ pruneStaleOpenClawRoutes(store, jobId, routeSessionKey);
86077
+ store.upsertSession({
86078
+ sessionKey: routeSessionKey,
86079
+ jobId,
86080
+ myAgentId: sessionKey,
86081
+ groupId: OPENCLAW_GATEWAY_ROUTE_GROUP_ID
86082
+ });
86083
+ return sessionKey;
86084
+ }
86085
+ function resolveOpenClawGatewayRoute(store, input) {
86086
+ if (!store) {
86087
+ return null;
86088
+ }
86089
+ const jobId = normalizeText(input.jobId) ?? inferJobIdFromSessionKey2(normalizeText(input.sessionKey));
86090
+ if (!jobId) {
86091
+ return null;
86092
+ }
86093
+ const route = store.querySessions({ jobId, limit: 25 }).find((session) => isOpenClawGatewayRoute(session));
86094
+ if (!route || !route.myAgentId) {
86095
+ return null;
86096
+ }
86097
+ return {
86098
+ sessionKey: route.myAgentId,
86099
+ jobId,
86100
+ routeSessionKey: route.sessionKey,
86101
+ updatedAt: route.updatedAt
86102
+ };
86103
+ }
86104
+ function isValidOpenClawGatewaySessionKey(sessionKey) {
86105
+ return validateOpenClawGatewaySessionKey(sessionKey).ok;
86106
+ }
86107
+ function buildOpenClawRouteSessionKey(jobId, gatewaySessionKey) {
86108
+ return [
86109
+ OPENCLAW_USER_SESSION_ROUTE_KEY_PREFIX,
86110
+ encodeURIComponent(jobId),
86111
+ encodeURIComponent(gatewaySessionKey)
86112
+ ].join(":");
86113
+ }
86114
+ function isOpenClawGatewayRoute(session) {
86115
+ return session.groupId === OPENCLAW_GATEWAY_ROUTE_GROUP_ID && validateOpenClawGatewaySessionKey(session.myAgentId).ok;
86116
+ }
86117
+ function findExistingValidOpenClawRoute(store, jobId) {
86118
+ return resolveOpenClawGatewayRoute(store, { jobId });
86119
+ }
86120
+ function pruneStaleOpenClawRoutes(store, jobId, keepRouteSessionKey) {
86121
+ if (!store.deleteSession) {
86122
+ return;
86123
+ }
86124
+ for (const session of store.querySessions({ jobId, limit: 100 })) {
86125
+ if (session.groupId === OPENCLAW_GATEWAY_ROUTE_GROUP_ID && session.sessionKey !== keepRouteSessionKey) {
86126
+ store.deleteSession(session.sessionKey);
86127
+ }
86128
+ }
86129
+ }
86130
+ function validateOpenClawGatewaySessionKey(sessionKey) {
86131
+ const key = normalizeText(sessionKey);
86132
+ if (!key) {
86133
+ return { ok: false, reason: "missing_gateway_session_key" };
86134
+ }
86135
+ if (key.startsWith("backup:")) {
86136
+ return { ok: false, reason: "internal_gateway_session_key", sessionKey: key };
86137
+ }
86138
+ if (key === "agent:main") {
86139
+ return { ok: true, sessionKey: key };
86140
+ }
86141
+ const parts = key.split(":");
86142
+ if (parts.length < 4 || parts[0] !== "agent" || !parts[1]) {
86143
+ return { ok: false, reason: "invalid_gateway_session_key", sessionKey: key };
86144
+ }
86145
+ const platform = parts[2];
86146
+ if (!platform || platform === "okx-a2a") {
86147
+ return { ok: false, reason: "internal_gateway_session_key", sessionKey: key };
86148
+ }
86149
+ return { ok: true, sessionKey: key };
86150
+ }
86151
+ function deriveOpenClawGatewaySessionKey(input) {
86152
+ const chatId = encodeURIComponent(input.chatId);
86153
+ const threadId = input.threadId ? encodeURIComponent(input.threadId) : "";
86154
+ if (input.platform === "telegram") {
86155
+ return threadId ? `agent:main:telegram:group:${chatId}:topic:${threadId}` : `agent:main:telegram:direct:${chatId}`;
86156
+ }
86157
+ return threadId ? `agent:main:${input.platform}:thread:${chatId}:${threadId}` : `agent:main:${input.platform}:dm:${chatId}`;
86158
+ }
86159
+ function logOpenClawRouteSkip(reason, input) {
86160
+ if (reason === "missing_gateway_session_key") {
86161
+ return;
86162
+ }
86163
+ console.error(
86164
+ `[openclaw-route] skipped gateway route bind reason=${reason} jobId=${input.jobId} sessionKey=${input.sessionKey ?? "(none)"} existingRoute=${input.existingRoute?.sessionKey ?? "(none)"}`
86165
+ );
86166
+ }
86167
+ function inferJobIdFromSessionKey2(sessionKey) {
86168
+ if (!sessionKey) {
86169
+ return null;
86170
+ }
86171
+ const parts = sessionKey.split(":");
86172
+ if (parts.length >= 2 && parts[0] === "job") {
86173
+ return safeDecode2(parts[1]);
86174
+ }
86175
+ if (sessionKey.startsWith("backup:")) {
86176
+ return safeDecode2(sessionKey.slice("backup:".length));
86177
+ }
86178
+ return null;
86179
+ }
86180
+ function normalizeText(value) {
86181
+ const text = value?.trim();
86182
+ return text ? text : null;
86183
+ }
86184
+ function safeDecode2(value) {
86185
+ try {
86186
+ return decodeURIComponent(value);
86187
+ } catch {
86188
+ return value;
86189
+ }
86190
+ }
86191
+
86030
86192
  // src/outbound-behavior.ts
86031
86193
  var SqliteOutboundBehavior = class {
86032
86194
  provider;
@@ -86248,6 +86410,11 @@ var GatewayOutboundBehavior = class {
86248
86410
  });
86249
86411
  }
86250
86412
  async dispatchUser(input) {
86413
+ const routed = this.resolveUserGatewaySessionKey(input);
86414
+ if (routed) {
86415
+ await this.dispatchUserToGatewaySession(input, routed);
86416
+ return null;
86417
+ }
86251
86418
  console.error(
86252
86419
  `${GATEWAY_OUTBOUND_LOG_PREFIX} dispatchUser latestUserSessions jobId=${input.jobId ?? "(none)"} idempotencyKey=${input.idempotencyKey ?? "(none)"}`
86253
86420
  );
@@ -86290,7 +86457,85 @@ var GatewayOutboundBehavior = class {
86290
86457
  }
86291
86458
  return null;
86292
86459
  }
86460
+ resolveUserGatewaySessionKey(input) {
86461
+ const route = resolveOpenClawGatewayRoute(this.sessionMetaStore, input);
86462
+ if (route) {
86463
+ return { sessionKey: route.sessionKey, source: "stored_openclaw_route" };
86464
+ }
86465
+ if (input.sessionKey?.startsWith("agent:")) {
86466
+ return isValidOpenClawGatewaySessionKey(input.sessionKey) ? { sessionKey: input.sessionKey, source: "explicit_gateway_session" } : null;
86467
+ }
86468
+ if (input.sessionKey) {
86469
+ return {
86470
+ sessionKey: this.resolveGatewaySessionKey({ ...input, sessionKey: input.sessionKey }),
86471
+ source: "derived_a2a_session"
86472
+ };
86473
+ }
86474
+ return null;
86475
+ }
86476
+ async dispatchUserToGatewaySession(input, routed) {
86477
+ console.error(
86478
+ `${GATEWAY_OUTBOUND_LOG_PREFIX} dispatchUser chatInject sessionKey=${input.sessionKey ?? "(none)"} gatewaySessionKey=${routed.sessionKey} source=${routed.source} jobId=${input.jobId ?? "(none)"} idempotencyKey=${input.idempotencyKey ?? "(none)"}`
86479
+ );
86480
+ try {
86481
+ await this.gateway.callChatInject({
86482
+ sessionKey: routed.sessionKey,
86483
+ message: input.userContent,
86484
+ label: "okx-a2a"
86485
+ });
86486
+ console.error(`${GATEWAY_OUTBOUND_LOG_PREFIX} dispatchUser chatInject ok gatewaySessionKey=${routed.sessionKey} source=${routed.source}`);
86487
+ logger.info(LogEvent.USER_DISPATCHED, gatewayOutboundExtra("chat.inject", {
86488
+ sessionKey: input.sessionKey ?? "",
86489
+ gatewaySessionKey: routed.sessionKey,
86490
+ jobId: input.jobId ?? "",
86491
+ source: routed.source,
86492
+ status: "delivered"
86493
+ }));
86494
+ } catch (err2) {
86495
+ if (!this.store || !isRetryableOpenClawGatewayError(err2)) {
86496
+ logger.error(LogEvent.USER_DISPATCH_FAILED, err2 instanceof Error ? err2 : new Error(String(err2)), gatewayOutboundExtra("chat.inject", {
86497
+ sessionKey: input.sessionKey ?? "",
86498
+ gatewaySessionKey: routed.sessionKey,
86499
+ jobId: input.jobId ?? "",
86500
+ source: routed.source,
86501
+ status: "failed"
86502
+ }));
86503
+ throw err2;
86504
+ }
86505
+ this.store.enqueuePendingGatewayDelivery({
86506
+ kind: "chat_inject",
86507
+ provider: this.provider,
86508
+ sessionKey: routed.sessionKey,
86509
+ content: input.userContent,
86510
+ jobId: input.jobId ?? null,
86511
+ messageId: input.idempotencyKey ?? null
86512
+ });
86513
+ console.error(
86514
+ `${GATEWAY_OUTBOUND_LOG_PREFIX} dispatchUser chatInject buffered gatewaySessionKey=${routed.sessionKey} source=${routed.source} idempotencyKey=${input.idempotencyKey ?? "(none)"}: ${err2 instanceof Error ? err2.message : String(err2)}`
86515
+ );
86516
+ logger.error(LogEvent.USER_DISPATCH_FAILED, err2 instanceof Error ? err2 : new Error(String(err2)), gatewayOutboundExtra("chat.inject", {
86517
+ sessionKey: input.sessionKey ?? "",
86518
+ gatewaySessionKey: routed.sessionKey,
86519
+ jobId: input.jobId ?? "",
86520
+ source: routed.source,
86521
+ status: "buffered"
86522
+ }));
86523
+ logger.info(LogEvent.GATEWAY_DELIVERY_BUFFERED, gatewayOutboundExtra("chat.inject", {
86524
+ sessionKey: input.sessionKey ?? "",
86525
+ gatewaySessionKey: routed.sessionKey,
86526
+ jobId: input.jobId ?? "",
86527
+ messageId: input.idempotencyKey ?? "",
86528
+ source: routed.source,
86529
+ status: "buffered"
86530
+ }));
86531
+ }
86532
+ }
86293
86533
  async promptUser(input) {
86534
+ const routed = this.resolveUserGatewaySessionKey(input);
86535
+ if (routed) {
86536
+ await this.promptUserToGatewaySession(input, routed);
86537
+ return null;
86538
+ }
86294
86539
  console.error(
86295
86540
  `${GATEWAY_OUTBOUND_LOG_PREFIX} promptUser latestUserSessions jobId=${input.jobId ?? "(none)"} idempotencyKey=${input.idempotencyKey ?? "(none)"}`
86296
86541
  );
@@ -86337,6 +86582,71 @@ var GatewayOutboundBehavior = class {
86337
86582
  }
86338
86583
  return null;
86339
86584
  }
86585
+ async promptUserToGatewaySession(input, routed) {
86586
+ console.error(
86587
+ `${GATEWAY_OUTBOUND_LOG_PREFIX} promptUser routed sessionKey=${input.sessionKey ?? "(none)"} gatewaySessionKey=${routed.sessionKey} source=${routed.source} jobId=${input.jobId ?? "(none)"} idempotencyKey=${input.idempotencyKey ?? "(none)"}`
86588
+ );
86589
+ let llmSent = false;
86590
+ try {
86591
+ await this.gateway.callSessionsSend({
86592
+ key: routed.sessionKey,
86593
+ message: input.llmContent,
86594
+ ...input.idempotencyKey ? { idempotencyKey: input.idempotencyKey } : {}
86595
+ });
86596
+ llmSent = true;
86597
+ await this.gateway.callChatInject({
86598
+ sessionKey: routed.sessionKey,
86599
+ message: input.userContent,
86600
+ label: "okx-a2a"
86601
+ });
86602
+ console.error(`${GATEWAY_OUTBOUND_LOG_PREFIX} promptUser routed ok gatewaySessionKey=${routed.sessionKey} source=${routed.source}`);
86603
+ logger.info(LogEvent.PROMPT_USER_CHECKPOINT, gatewayOutboundExtra("routed_prompt_user", {
86604
+ sessionKey: input.sessionKey ?? "",
86605
+ gatewaySessionKey: routed.sessionKey,
86606
+ jobId: input.jobId ?? "",
86607
+ source: routed.source,
86608
+ status: "delivered"
86609
+ }));
86610
+ } catch (err2) {
86611
+ if (!this.store || !isRetryableOpenClawGatewayError(err2)) {
86612
+ logger.error(LogEvent.PROMPT_USER_FAILED, err2 instanceof Error ? err2 : new Error(String(err2)), gatewayOutboundExtra("routed_prompt_user", {
86613
+ sessionKey: input.sessionKey ?? "",
86614
+ gatewaySessionKey: routed.sessionKey,
86615
+ jobId: input.jobId ?? "",
86616
+ source: routed.source,
86617
+ status: "failed"
86618
+ }));
86619
+ throw err2;
86620
+ }
86621
+ this.store.enqueuePendingGatewayDelivery({
86622
+ kind: "chat_inject",
86623
+ provider: this.provider,
86624
+ sessionKey: routed.sessionKey,
86625
+ content: input.userContent,
86626
+ llmContent: llmSent ? null : input.llmContent,
86627
+ jobId: input.jobId ?? null,
86628
+ messageId: input.idempotencyKey ?? null
86629
+ });
86630
+ console.error(
86631
+ `${GATEWAY_OUTBOUND_LOG_PREFIX} promptUser routed buffered gatewaySessionKey=${routed.sessionKey} source=${routed.source} llmSent=${llmSent ? 1 : 0} idempotencyKey=${input.idempotencyKey ?? "(none)"}: ${err2 instanceof Error ? err2.message : String(err2)}`
86632
+ );
86633
+ logger.error(LogEvent.PROMPT_USER_FAILED, err2 instanceof Error ? err2 : new Error(String(err2)), gatewayOutboundExtra("routed_prompt_user", {
86634
+ sessionKey: input.sessionKey ?? "",
86635
+ gatewaySessionKey: routed.sessionKey,
86636
+ jobId: input.jobId ?? "",
86637
+ source: routed.source,
86638
+ status: "buffered"
86639
+ }));
86640
+ logger.info(LogEvent.GATEWAY_DELIVERY_BUFFERED, gatewayOutboundExtra("routed_prompt_user", {
86641
+ sessionKey: input.sessionKey ?? "",
86642
+ gatewaySessionKey: routed.sessionKey,
86643
+ jobId: input.jobId ?? "",
86644
+ messageId: input.idempotencyKey ?? "",
86645
+ source: routed.source,
86646
+ status: "buffered"
86647
+ }));
86648
+ }
86649
+ }
86340
86650
  };
86341
86651
  function createOutboundBehavior(provider, deps) {
86342
86652
  if (provider === "openclaw") {
@@ -86565,6 +86875,12 @@ function bindOutboundJobProviderToCurrentDefault(sessionStore, jobId) {
86565
86875
  console.log(`[okx-agent-task] job provider bind failed from outbound-xmtp: job=${jobId}`, err2);
86566
86876
  }
86567
86877
  }
86878
+ function bindOutboundOpenClawRouteIfCurrent(sessionStore, jobId) {
86879
+ const provider = resolveConfiguredAiProviderForJob({ store: sessionStore, jobId });
86880
+ if (provider === "openclaw") {
86881
+ bindOpenClawGatewayRouteFromEnv(sessionStore, { jobId });
86882
+ }
86883
+ }
86568
86884
  function buildTaskPayload(replyToMessageId) {
86569
86885
  return {
86570
86886
  taskMinVersion: TASK_MIN_VERSION,
@@ -87327,7 +87643,7 @@ async function handleXmtpSendCommand(params) {
87327
87643
  const sessionStore2 = params.sessionStore ?? ownedStore2;
87328
87644
  try {
87329
87645
  bindOutboundJobProviderToCurrentDefault(sessionStore2, command.jobId);
87330
- resolveConfiguredAiProviderForJob({ store: sessionStore2, jobId: command.jobId });
87646
+ bindOutboundOpenClawRouteIfCurrent(sessionStore2, command.jobId);
87331
87647
  return await handleSqliteGroupSendCommand({
87332
87648
  command,
87333
87649
  service,
@@ -87341,7 +87657,7 @@ async function handleXmtpSendCommand(params) {
87341
87657
  const sessionStore = params.sessionStore ?? ownedStore;
87342
87658
  try {
87343
87659
  bindOutboundJobProviderToCurrentDefault(sessionStore, command.jobId);
87344
- resolveConfiguredAiProviderForJob({ store: sessionStore, jobId: command.jobId });
87660
+ bindOutboundOpenClawRouteIfCurrent(sessionStore, command.jobId);
87345
87661
  const { file, sessionAgentId } = await readFileForSend({
87346
87662
  command,
87347
87663
  store,
@@ -89317,7 +89633,7 @@ function userWatchEventDeliveredSentryExtra(event) {
89317
89633
  var environment = process.env.SENTRY_ENV === "dev" ? "dev" : "prod";
89318
89634
  var SENTRY_CONFIG = {
89319
89635
  projectName: "okx/openclaw-okx-a2a-extension",
89320
- release: "0.0.12",
89636
+ release: "0.0.13-beta-d0ec14bc63-260622110355",
89321
89637
  environment
89322
89638
  };
89323
89639
 
@@ -89436,12 +89752,12 @@ async function runListenerWithLock(options, paths) {
89436
89752
  }));
89437
89753
  }
89438
89754
  });
89439
- service.setPluginVersion("0.0.12");
89755
+ service.setPluginVersion("0.0.13-beta-d0ec14bc63-260622110355");
89440
89756
  await service.init();
89441
89757
  const pluginVersionStatus = service.pluginVersionStatus;
89442
89758
  if (pluginVersionStatus.unavailable) {
89443
89759
  throw new Error(
89444
- `@okxweb3/a2a-node v${"0.0.12"} is below the required minimum v${pluginVersionStatus.minVersion}`
89760
+ `@okxweb3/a2a-node v${"0.0.13-beta-d0ec14bc63-260622110355"} is below the required minimum v${pluginVersionStatus.minVersion}`
89445
89761
  );
89446
89762
  }
89447
89763
  const systemConfig = service.getSystemConfig();
@@ -89459,7 +89775,7 @@ async function runListenerWithLock(options, paths) {
89459
89775
  onchainosAgentId: "*",
89460
89776
  reason: "system-config missing sentryDsn",
89461
89777
  pluginId: "@okxweb3/a2a-node",
89462
- pluginVersion: "0.0.12"
89778
+ pluginVersion: "0.0.13-beta-d0ec14bc63-260622110355"
89463
89779
  });
89464
89780
  }
89465
89781
  console.log(
@@ -89747,6 +90063,7 @@ function parsePluginYamlVersion(content3) {
89747
90063
  GatewayOutboundBehavior,
89748
90064
  InvalidXmtpMessageStore,
89749
90065
  OFFLINE_REPLAY_SYNC_INTERVAL,
90066
+ OPENCLAW_GATEWAY_ROUTE_GROUP_ID,
89750
90067
  SYSTEM_NOTIFICATION_SESSION_KEY,
89751
90068
  SessionStore,
89752
90069
  SqliteOutboundBehavior,
@@ -89760,6 +90077,7 @@ function parsePluginYamlVersion(content3) {
89760
90077
  bindJobProviderToCurrentDefaultIfMissing,
89761
90078
  bindJobProviderToCurrentRuntimeIfMissing,
89762
90079
  bindMessageJobProviderToCurrentDefault,
90080
+ bindOpenClawGatewayRouteFromEnv,
89763
90081
  buildAgentMessageNotice,
89764
90082
  buildAiAdapterCommand,
89765
90083
  buildAiProviderEnv,
@@ -89780,6 +90098,7 @@ function parsePluginYamlVersion(content3) {
89780
90098
  createFileMessageHandler,
89781
90099
  createOutboundBehavior,
89782
90100
  createUserAttentionWatchParentMonitor,
90101
+ currentOpenClawGatewaySessionKey,
89783
90102
  detectAiProviders,
89784
90103
  detectCurrentAiProvider,
89785
90104
  detectGatewayInvocation,
@@ -89813,6 +90132,7 @@ function parsePluginYamlVersion(content3) {
89813
90132
  resolveConfiguredAiProviderForJob,
89814
90133
  resolveDirectCommunicationSessionTarget,
89815
90134
  resolveOpenClawGatewayConfig,
90135
+ resolveOpenClawGatewayRoute,
89816
90136
  resolveSystemNotificationTargets,
89817
90137
  resolveTaskConfigPath,
89818
90138
  resolveTaskHome,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@okxweb3/a2a-node",
3
- "version": "0.0.12",
3
+ "version": "0.0.13-beta-d0ec14bc63-260622110355",
4
4
  "description": "Host-agnostic Node CLI for E2E encrypted agent-to-agent communication via XMTP",
5
5
  "main": "dist/index.js",
6
6
  "bin": {