@okxweb3/a2a-node 0.0.17 → 0.0.18-beta-8614cb2a91-260625165344

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 +268 -115
  2. package/dist/index.js +99 -57
  3. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -212,6 +212,18 @@ function normalizeOptionalJobId(jobId) {
212
212
  const normalized = jobId?.trim();
213
213
  return normalized ? normalized : null;
214
214
  }
215
+ function normalizeOptionalExpireTime(expireTime) {
216
+ if (expireTime === null || expireTime === void 0) {
217
+ return null;
218
+ }
219
+ if (!Number.isSafeInteger(expireTime) || expireTime < 0) {
220
+ throw new Error("expireTime must be a non-negative integer Unix timestamp in seconds");
221
+ }
222
+ return expireTime;
223
+ }
224
+ function activeUserAttentionSql() {
225
+ return "(expire_time IS NULL OR expire_time >= ?)";
226
+ }
215
227
  function normalizeJobIdList(jobIds) {
216
228
  return [...new Set(jobIds.map((jobId) => normalizeOptionalJobId(jobId)).filter(isNonNullString))];
217
229
  }
@@ -290,6 +302,7 @@ function mapAttentionRow(row) {
290
302
  ...mapChoices(row.choices_json ?? null),
291
303
  userContent: row.user_content,
292
304
  ...row.idempotency_key ? { idempotencyKey: row.idempotency_key } : {},
305
+ ...typeof row.expire_time === "number" ? { expireTime: row.expire_time } : {},
293
306
  createdAt: row.created_at,
294
307
  ...row.handled_at ? { handledAt: row.handled_at } : {}
295
308
  };
@@ -501,6 +514,7 @@ var init_session_store = __esm({
501
514
  choices_json TEXT,
502
515
  user_content TEXT NOT NULL,
503
516
  idempotency_key TEXT UNIQUE,
517
+ expire_time INTEGER,
504
518
  created_at TEXT NOT NULL,
505
519
  handled_at TEXT,
506
520
  deleted_at TEXT,
@@ -515,6 +529,7 @@ var init_session_store = __esm({
515
529
  this.ensureColumn("user_attention", "deleted_at", "TEXT");
516
530
  this.ensureColumn("user_attention", "seen", "INTEGER NOT NULL DEFAULT 0");
517
531
  this.ensureColumn("user_attention", "provider", "TEXT CHECK (provider IN ('codex', 'claude', 'hermes', 'openclaw') OR provider IS NULL)");
532
+ this.ensureColumn("user_attention", "expire_time", "INTEGER");
518
533
  this.db.exec(`
519
534
  CREATE INDEX IF NOT EXISTS idx_user_attention_provider_status_created
520
535
  ON user_attention(provider, status, created_at)
@@ -932,6 +947,7 @@ var init_session_store = __esm({
932
947
  }
933
948
  const provider = normalizeOptionalProvider(input.provider);
934
949
  const choicesJson = normalizeChoicesJson(input.choices);
950
+ const expireTime = normalizeOptionalExpireTime(input.expireTime);
935
951
  return this.transaction(() => {
936
952
  if (input.idempotencyKey) {
937
953
  const existing = this.getUserAttentionByIdempotencyKey(input.idempotencyKey);
@@ -947,15 +963,15 @@ var init_session_store = __esm({
947
963
  const statement = input.idempotencyKey ? this.db.prepare(`
948
964
  INSERT OR IGNORE INTO user_attention (
949
965
  id, kind, provider, status, job_id, session_key, llm_content, choices_json, user_content,
950
- idempotency_key, created_at, handled_at
966
+ idempotency_key, expire_time, created_at, handled_at
951
967
  )
952
- VALUES (?, ?, ?, 'pending', ?, ?, ?, ?, ?, ?, ?, NULL)
968
+ VALUES (?, ?, ?, 'pending', ?, ?, ?, ?, ?, ?, ?, ?, NULL)
953
969
  `) : this.db.prepare(`
954
970
  INSERT INTO user_attention (
955
971
  id, kind, provider, status, job_id, session_key, llm_content, choices_json, user_content,
956
- idempotency_key, created_at, handled_at
972
+ idempotency_key, expire_time, created_at, handled_at
957
973
  )
958
- VALUES (?, ?, ?, 'pending', ?, ?, ?, ?, ?, NULL, ?, NULL)
974
+ VALUES (?, ?, ?, 'pending', ?, ?, ?, ?, ?, NULL, ?, ?, NULL)
959
975
  `);
960
976
  if (input.idempotencyKey) {
961
977
  statement.run(
@@ -968,6 +984,7 @@ var init_session_store = __esm({
968
984
  choicesJson,
969
985
  input.userContent,
970
986
  input.idempotencyKey,
987
+ expireTime,
971
988
  createdAt
972
989
  );
973
990
  const existing = this.getUserAttentionByIdempotencyKey(input.idempotencyKey);
@@ -985,6 +1002,7 @@ var init_session_store = __esm({
985
1002
  input.llmContent ?? null,
986
1003
  choicesJson,
987
1004
  input.userContent,
1005
+ expireTime,
988
1006
  createdAt
989
1007
  );
990
1008
  const item = this.getUserAttention(id);
@@ -1001,6 +1019,8 @@ var init_session_store = __esm({
1001
1019
  if (!options.includeHandled) {
1002
1020
  conditions.push("status = 'pending'");
1003
1021
  }
1022
+ conditions.push(activeUserAttentionSql());
1023
+ values.push(this.currentUnixSeconds());
1004
1024
  if (options.provider) {
1005
1025
  assertAiProvider(options.provider);
1006
1026
  conditions.push("provider = ?");
@@ -1042,19 +1062,21 @@ var init_session_store = __esm({
1042
1062
  AND status = 'pending'
1043
1063
  AND seen = 0
1044
1064
  AND deleted_at IS NULL
1065
+ AND ${activeUserAttentionSql()}
1045
1066
  ${watchFilter.sql}
1046
1067
  ORDER BY created_at DESC, id DESC
1047
1068
  LIMIT 1
1048
- `).get(...watchFilter.values);
1069
+ `).get(this.currentUnixSeconds(), ...watchFilter.values);
1049
1070
  const notifications = this.db.prepare(`
1050
1071
  SELECT * FROM user_attention
1051
1072
  WHERE kind = 'notification'
1052
1073
  AND status = 'pending'
1053
1074
  AND seen = 0
1054
1075
  AND deleted_at IS NULL
1076
+ AND ${activeUserAttentionSql()}
1055
1077
  ${watchFilter.sql}
1056
1078
  ORDER BY created_at ASC, id ASC
1057
- `).all(...watchFilter.values);
1079
+ `).all(this.currentUnixSeconds(), ...watchFilter.values);
1058
1080
  if (!decision && notifications.length === 0) {
1059
1081
  return { items: [], hasDecision: false };
1060
1082
  }
@@ -1276,9 +1298,10 @@ var init_session_store = __esm({
1276
1298
  AND status = 'pending'
1277
1299
  AND seen = 1
1278
1300
  AND deleted_at IS NULL
1301
+ AND ${activeUserAttentionSql()}
1279
1302
  ${providerFilter}
1280
1303
  ORDER BY created_at ASC, id ASC
1281
- `).all(...values);
1304
+ `).all(this.currentUnixSeconds(), ...values);
1282
1305
  return rows.map(mapAttentionRow);
1283
1306
  }
1284
1307
  markUserAttentionHandled(ids) {
@@ -1489,6 +1512,9 @@ var init_session_store = __esm({
1489
1512
  timestamp() {
1490
1513
  return this.now().toISOString();
1491
1514
  }
1515
+ currentUnixSeconds() {
1516
+ return Math.floor(this.now().getTime() / 1e3);
1517
+ }
1492
1518
  };
1493
1519
  }
1494
1520
  });
@@ -7551,7 +7577,7 @@ function buildConnectParams(config, instanceId, protocolVersion) {
7551
7577
  client: {
7552
7578
  id: "gateway-client",
7553
7579
  displayName: "okx-a2a-node",
7554
- version: "0.0.17",
7580
+ version: "0.0.18-beta-8614cb2a91-260625165344",
7555
7581
  platform: "node",
7556
7582
  mode: "backend",
7557
7583
  instanceId
@@ -7562,7 +7588,7 @@ function buildConnectParams(config, instanceId, protocolVersion) {
7562
7588
  commands: [],
7563
7589
  permissions: {},
7564
7590
  locale: Intl.DateTimeFormat().resolvedOptions().locale || "en-US",
7565
- userAgent: `okx-a2a-node/${"0.0.17"}`,
7591
+ userAgent: `okx-a2a-node/${"0.0.18-beta-8614cb2a91-260625165344"}`,
7566
7592
  auth: {
7567
7593
  ...config.token ? { token: config.token } : {},
7568
7594
  ...config.password ? { password: config.password } : {}
@@ -24001,6 +24027,9 @@ var init_sentry_logger = __esm({
24001
24027
  });
24002
24028
 
24003
24029
  // src/outbound-behavior.ts
24030
+ function resolveUserDeliveryId(input) {
24031
+ return input.idempotencyKey?.trim() || (0, import_node_crypto5.randomUUID)();
24032
+ }
24004
24033
  function gatewayOutboundExtra(operation, extra = {}) {
24005
24034
  return {
24006
24035
  source: "node_gateway_outbound",
@@ -24058,11 +24087,12 @@ function createOutboundBehavior(provider, deps) {
24058
24087
  }
24059
24088
  return new SqliteOutboundBehavior(provider, deps);
24060
24089
  }
24061
- var SqliteOutboundBehavior, DEFAULT_GATEWAY_PORT2, GATEWAY_OUTBOUND_LOG_PREFIX, GatewayOutboundBehavior;
24090
+ var import_node_crypto5, SqliteOutboundBehavior, DEFAULT_GATEWAY_PORT2, GATEWAY_OUTBOUND_LOG_PREFIX, GatewayOutboundBehavior;
24062
24091
  var init_outbound_behavior = __esm({
24063
24092
  "src/outbound-behavior.ts"() {
24064
24093
  "use strict";
24065
24094
  init_log();
24095
+ import_node_crypto5 = require("node:crypto");
24066
24096
  init_user_attention_ipc();
24067
24097
  init_openclaw_gateway();
24068
24098
  init_openclaw_session_key();
@@ -24110,7 +24140,8 @@ var init_outbound_behavior = __esm({
24110
24140
  userContent: input.userContent,
24111
24141
  jobId: input.jobId ?? null,
24112
24142
  sessionKey: input.sessionKey ?? null,
24113
- idempotencyKey: input.idempotencyKey ?? null
24143
+ idempotencyKey: input.idempotencyKey ?? null,
24144
+ expireTime: input.expireTime ?? null
24114
24145
  });
24115
24146
  await notifyUserAttentionChanged(this.store.homeDir);
24116
24147
  return item;
@@ -24124,7 +24155,8 @@ var init_outbound_behavior = __esm({
24124
24155
  choices: input.choices ?? null,
24125
24156
  jobId: input.jobId ?? null,
24126
24157
  sessionKey: input.sessionKey ?? null,
24127
- idempotencyKey: input.idempotencyKey ?? null
24158
+ idempotencyKey: input.idempotencyKey ?? null,
24159
+ expireTime: input.expireTime ?? null
24128
24160
  });
24129
24161
  await notifyUserAttentionChanged(this.store.homeDir);
24130
24162
  return item;
@@ -24271,19 +24303,21 @@ var init_outbound_behavior = __esm({
24271
24303
  });
24272
24304
  }
24273
24305
  async dispatchUser(input) {
24306
+ const deliveryId = resolveUserDeliveryId(input);
24274
24307
  const routed = this.resolveUserGatewaySessionKey(input);
24275
24308
  if (routed) {
24276
- await this.dispatchUserToGatewaySession(input, routed);
24309
+ await this.dispatchUserToGatewaySession(input, routed, deliveryId);
24277
24310
  return null;
24278
24311
  }
24279
24312
  errorWithTimestamp(
24280
- `${GATEWAY_OUTBOUND_LOG_PREFIX} dispatchUser latestUserSessions jobId=${input.jobId ?? "(none)"} idempotencyKey=${input.idempotencyKey ?? "(none)"}`
24313
+ `${GATEWAY_OUTBOUND_LOG_PREFIX} dispatchUser latestUserSessions jobId=${input.jobId ?? "(none)"} idempotencyKey=${deliveryId}`
24281
24314
  );
24282
24315
  try {
24283
24316
  const result = await this.gateway.callDispatchUserToLatestSessions({
24284
24317
  content: input.userContent,
24285
24318
  ...input.jobId ? { jobId: input.jobId } : {},
24286
- ...input.sessionKey ? { currentSessionKey: input.sessionKey } : {}
24319
+ ...input.sessionKey ? { currentSessionKey: input.sessionKey } : {},
24320
+ idempotencyKey: deliveryId
24287
24321
  });
24288
24322
  assertLatestUserFanoutDelivered("okx-a2a.dispatch_user", result);
24289
24323
  this.persistDeliveredFallbackRoutes(input.jobId, result);
@@ -24306,10 +24340,10 @@ var init_outbound_behavior = __esm({
24306
24340
  sessionKey: "openclaw:latest-user-sessions",
24307
24341
  content: input.userContent,
24308
24342
  jobId: input.jobId ?? null,
24309
- messageId: input.idempotencyKey ?? null
24343
+ messageId: deliveryId
24310
24344
  });
24311
24345
  errorWithTimestamp(
24312
- `${GATEWAY_OUTBOUND_LOG_PREFIX} dispatchUser latestUserSessions buffered idempotencyKey=${input.idempotencyKey ?? "(none)"}: ${err2 instanceof Error ? err2.message : String(err2)}`
24346
+ `${GATEWAY_OUTBOUND_LOG_PREFIX} dispatchUser latestUserSessions buffered idempotencyKey=${deliveryId}: ${err2 instanceof Error ? err2.message : String(err2)}`
24313
24347
  );
24314
24348
  logger.error(LogEvent.USER_DISPATCH_FAILED, err2 instanceof Error ? err2 : new Error(String(err2)), gatewayOutboundExtra("okx-a2a.dispatch_user", {
24315
24349
  jobId: input.jobId ?? "",
@@ -24317,7 +24351,7 @@ var init_outbound_behavior = __esm({
24317
24351
  }));
24318
24352
  logger.info(LogEvent.GATEWAY_DELIVERY_BUFFERED, gatewayOutboundExtra("okx-a2a.dispatch_user", {
24319
24353
  jobId: input.jobId ?? "",
24320
- messageId: input.idempotencyKey ?? "",
24354
+ messageId: deliveryId,
24321
24355
  status: "buffered"
24322
24356
  }));
24323
24357
  }
@@ -24353,16 +24387,17 @@ var init_outbound_behavior = __esm({
24353
24387
  }
24354
24388
  return null;
24355
24389
  }
24356
- async dispatchUserToGatewaySession(input, routed) {
24390
+ async dispatchUserToGatewaySession(input, routed, deliveryId) {
24357
24391
  const gatewaySessionKey = routed.sessionKeys.join(",");
24358
24392
  console.error(
24359
- `${GATEWAY_OUTBOUND_LOG_PREFIX} dispatchUser routed sessionKey=${input.sessionKey ?? "(none)"} gatewaySessionKey=${gatewaySessionKey} source=${routed.source} jobId=${input.jobId ?? "(none)"} idempotencyKey=${input.idempotencyKey ?? "(none)"}`
24393
+ `${GATEWAY_OUTBOUND_LOG_PREFIX} dispatchUser routed sessionKey=${input.sessionKey ?? "(none)"} gatewaySessionKey=${gatewaySessionKey} source=${routed.source} jobId=${input.jobId ?? "(none)"} idempotencyKey=${deliveryId}`
24360
24394
  );
24361
24395
  try {
24362
24396
  const result = await this.gateway.callDispatchUserToLatestSessions({
24363
24397
  content: input.userContent,
24364
24398
  label: "okx-a2a",
24365
- ...routed.source === "stored_openclaw_routes" ? { sessionKeys: routed.sessionKeys } : { sessionKey: routed.sessionKeys[0] }
24399
+ ...routed.source === "stored_openclaw_routes" ? { sessionKeys: routed.sessionKeys } : { sessionKey: routed.sessionKeys[0] },
24400
+ idempotencyKey: deliveryId
24366
24401
  });
24367
24402
  assertLatestUserFanoutDelivered("okx-a2a.dispatch_user", result);
24368
24403
  console.error(`${GATEWAY_OUTBOUND_LOG_PREFIX} dispatchUser routed ok gatewaySessionKey=${gatewaySessionKey} source=${routed.source}`);
@@ -24375,7 +24410,7 @@ var init_outbound_behavior = __esm({
24375
24410
  }));
24376
24411
  } catch (err2) {
24377
24412
  if (routed.source === "stored_openclaw_routes" && isNoDeliverableUserSessionError(err2)) {
24378
- await this.repairDispatchUserRoute(input, gatewaySessionKey, routed.source);
24413
+ await this.repairDispatchUserRoute(input, gatewaySessionKey, routed.source, deliveryId);
24379
24414
  return;
24380
24415
  }
24381
24416
  if (!this.store || !isRetryableOpenClawGatewayError(err2)) {
@@ -24394,10 +24429,10 @@ var init_outbound_behavior = __esm({
24394
24429
  sessionKey: routed.sessionKeys[0] ?? "openclaw:routed-user-sessions",
24395
24430
  content: input.userContent,
24396
24431
  jobId: input.jobId ?? null,
24397
- messageId: input.idempotencyKey ?? null
24432
+ messageId: deliveryId
24398
24433
  });
24399
24434
  console.error(
24400
- `${GATEWAY_OUTBOUND_LOG_PREFIX} dispatchUser routed buffered gatewaySessionKey=${gatewaySessionKey} source=${routed.source} idempotencyKey=${input.idempotencyKey ?? "(none)"}: ${err2 instanceof Error ? err2.message : String(err2)}`
24435
+ `${GATEWAY_OUTBOUND_LOG_PREFIX} dispatchUser routed buffered gatewaySessionKey=${gatewaySessionKey} source=${routed.source} idempotencyKey=${deliveryId}: ${err2 instanceof Error ? err2.message : String(err2)}`
24401
24436
  );
24402
24437
  logger.error(LogEvent.USER_DISPATCH_FAILED, err2 instanceof Error ? err2 : new Error(String(err2)), gatewayOutboundExtra("okx-a2a.dispatch_user", {
24403
24438
  sessionKey: input.sessionKey ?? "",
@@ -24410,20 +24445,21 @@ var init_outbound_behavior = __esm({
24410
24445
  sessionKey: input.sessionKey ?? "",
24411
24446
  gatewaySessionKey,
24412
24447
  jobId: input.jobId ?? "",
24413
- messageId: input.idempotencyKey ?? "",
24448
+ messageId: deliveryId,
24414
24449
  source: routed.source,
24415
24450
  status: "buffered"
24416
24451
  }));
24417
24452
  }
24418
24453
  }
24419
- async repairDispatchUserRoute(input, staleGatewaySessionKey, source) {
24454
+ async repairDispatchUserRoute(input, staleGatewaySessionKey, source, deliveryId) {
24420
24455
  console.error(
24421
24456
  `${GATEWAY_OUTBOUND_LOG_PREFIX} dispatchUser routeRepair latestUserSessions staleGatewaySessionKey=${staleGatewaySessionKey} jobId=${input.jobId ?? "(none)"}`
24422
24457
  );
24423
24458
  const result = await this.gateway.callDispatchUserToLatestSessions({
24424
24459
  content: input.userContent,
24425
24460
  ...input.jobId ? { jobId: input.jobId } : {},
24426
- ...input.sessionKey ? { currentSessionKey: input.sessionKey } : {}
24461
+ ...input.sessionKey ? { currentSessionKey: input.sessionKey } : {},
24462
+ idempotencyKey: deliveryId
24427
24463
  });
24428
24464
  assertLatestUserFanoutDelivered("okx-a2a.dispatch_user", result);
24429
24465
  this.persistDeliveredFallbackRoutes(input.jobId, result, { replaceExisting: true });
@@ -24440,20 +24476,22 @@ var init_outbound_behavior = __esm({
24440
24476
  }));
24441
24477
  }
24442
24478
  async promptUser(input) {
24479
+ const deliveryId = resolveUserDeliveryId(input);
24443
24480
  const routed = this.resolveUserGatewaySessionKey(input);
24444
24481
  if (routed) {
24445
- await this.promptUserToGatewaySession(input, routed);
24482
+ await this.promptUserToGatewaySession(input, routed, deliveryId);
24446
24483
  return null;
24447
24484
  }
24448
24485
  errorWithTimestamp(
24449
- `${GATEWAY_OUTBOUND_LOG_PREFIX} promptUser latestUserSessions jobId=${input.jobId ?? "(none)"} idempotencyKey=${input.idempotencyKey ?? "(none)"}`
24486
+ `${GATEWAY_OUTBOUND_LOG_PREFIX} promptUser latestUserSessions jobId=${input.jobId ?? "(none)"} idempotencyKey=${deliveryId}`
24450
24487
  );
24451
24488
  try {
24452
24489
  const result = await this.gateway.callPromptUserToLatestSessions({
24453
24490
  userContent: input.userContent,
24454
24491
  llmContent: input.llmContent,
24455
24492
  ...input.jobId ? { jobId: input.jobId } : {},
24456
- ...input.sessionKey ? { currentSessionKey: input.sessionKey } : {}
24493
+ ...input.sessionKey ? { currentSessionKey: input.sessionKey } : {},
24494
+ idempotencyKey: deliveryId
24457
24495
  });
24458
24496
  assertLatestUserFanoutDelivered("okx-a2a.prompt_user", result);
24459
24497
  this.persistDeliveredFallbackRoutes(input.jobId, result);
@@ -24477,10 +24515,10 @@ var init_outbound_behavior = __esm({
24477
24515
  content: input.userContent,
24478
24516
  llmContent: input.llmContent,
24479
24517
  jobId: input.jobId ?? null,
24480
- messageId: input.idempotencyKey ?? null
24518
+ messageId: deliveryId
24481
24519
  });
24482
24520
  errorWithTimestamp(
24483
- `${GATEWAY_OUTBOUND_LOG_PREFIX} promptUser latestUserSessions buffered idempotencyKey=${input.idempotencyKey ?? "(none)"}: ${err2 instanceof Error ? err2.message : String(err2)}`
24521
+ `${GATEWAY_OUTBOUND_LOG_PREFIX} promptUser latestUserSessions buffered idempotencyKey=${deliveryId}: ${err2 instanceof Error ? err2.message : String(err2)}`
24484
24522
  );
24485
24523
  logger.error(LogEvent.PROMPT_USER_FAILED, err2 instanceof Error ? err2 : new Error(String(err2)), gatewayOutboundExtra("okx-a2a.prompt_user", {
24486
24524
  jobId: input.jobId ?? "",
@@ -24488,22 +24526,23 @@ var init_outbound_behavior = __esm({
24488
24526
  }));
24489
24527
  logger.info(LogEvent.GATEWAY_DELIVERY_BUFFERED, gatewayOutboundExtra("okx-a2a.prompt_user", {
24490
24528
  jobId: input.jobId ?? "",
24491
- messageId: input.idempotencyKey ?? "",
24529
+ messageId: deliveryId,
24492
24530
  status: "buffered"
24493
24531
  }));
24494
24532
  }
24495
24533
  return null;
24496
24534
  }
24497
- async promptUserToGatewaySession(input, routed) {
24535
+ async promptUserToGatewaySession(input, routed, deliveryId) {
24498
24536
  const gatewaySessionKey = routed.sessionKeys.join(",");
24499
24537
  console.error(
24500
- `${GATEWAY_OUTBOUND_LOG_PREFIX} promptUser routed sessionKey=${input.sessionKey ?? "(none)"} gatewaySessionKey=${gatewaySessionKey} source=${routed.source} jobId=${input.jobId ?? "(none)"} idempotencyKey=${input.idempotencyKey ?? "(none)"}`
24538
+ `${GATEWAY_OUTBOUND_LOG_PREFIX} promptUser routed sessionKey=${input.sessionKey ?? "(none)"} gatewaySessionKey=${gatewaySessionKey} source=${routed.source} jobId=${input.jobId ?? "(none)"} idempotencyKey=${deliveryId}`
24501
24539
  );
24502
24540
  try {
24503
24541
  const result = await this.gateway.callPromptUserToLatestSessions({
24504
24542
  userContent: input.userContent,
24505
24543
  llmContent: input.llmContent,
24506
- ...routed.source === "stored_openclaw_routes" ? { sessionKeys: routed.sessionKeys } : { sessionKey: routed.sessionKeys[0] }
24544
+ ...routed.source === "stored_openclaw_routes" ? { sessionKeys: routed.sessionKeys } : { sessionKey: routed.sessionKeys[0] },
24545
+ idempotencyKey: deliveryId
24507
24546
  });
24508
24547
  assertLatestUserFanoutDelivered("okx-a2a.prompt_user", result);
24509
24548
  console.error(`${GATEWAY_OUTBOUND_LOG_PREFIX} promptUser routed ok gatewaySessionKey=${gatewaySessionKey} source=${routed.source}`);
@@ -24516,7 +24555,7 @@ var init_outbound_behavior = __esm({
24516
24555
  }));
24517
24556
  } catch (err2) {
24518
24557
  if (routed.source === "stored_openclaw_routes" && isNoDeliverableUserSessionError(err2)) {
24519
- await this.repairPromptUserRoute(input, gatewaySessionKey, routed.source);
24558
+ await this.repairPromptUserRoute(input, gatewaySessionKey, routed.source, deliveryId);
24520
24559
  return;
24521
24560
  }
24522
24561
  if (!this.store || !isRetryableOpenClawGatewayError(err2)) {
@@ -24536,10 +24575,10 @@ var init_outbound_behavior = __esm({
24536
24575
  content: input.userContent,
24537
24576
  llmContent: input.llmContent,
24538
24577
  jobId: input.jobId ?? null,
24539
- messageId: input.idempotencyKey ?? null
24578
+ messageId: deliveryId
24540
24579
  });
24541
24580
  console.error(
24542
- `${GATEWAY_OUTBOUND_LOG_PREFIX} promptUser routed buffered gatewaySessionKey=${gatewaySessionKey} source=${routed.source} idempotencyKey=${input.idempotencyKey ?? "(none)"}: ${err2 instanceof Error ? err2.message : String(err2)}`
24581
+ `${GATEWAY_OUTBOUND_LOG_PREFIX} promptUser routed buffered gatewaySessionKey=${gatewaySessionKey} source=${routed.source} idempotencyKey=${deliveryId}: ${err2 instanceof Error ? err2.message : String(err2)}`
24543
24582
  );
24544
24583
  logger.error(LogEvent.PROMPT_USER_FAILED, err2 instanceof Error ? err2 : new Error(String(err2)), gatewayOutboundExtra("routed_prompt_user", {
24545
24584
  sessionKey: input.sessionKey ?? "",
@@ -24552,13 +24591,13 @@ var init_outbound_behavior = __esm({
24552
24591
  sessionKey: input.sessionKey ?? "",
24553
24592
  gatewaySessionKey,
24554
24593
  jobId: input.jobId ?? "",
24555
- messageId: input.idempotencyKey ?? "",
24594
+ messageId: deliveryId,
24556
24595
  source: routed.source,
24557
24596
  status: "buffered"
24558
24597
  }));
24559
24598
  }
24560
24599
  }
24561
- async repairPromptUserRoute(input, staleGatewaySessionKey, source) {
24600
+ async repairPromptUserRoute(input, staleGatewaySessionKey, source, deliveryId) {
24562
24601
  console.error(
24563
24602
  `${GATEWAY_OUTBOUND_LOG_PREFIX} promptUser routeRepair latestUserSessions staleGatewaySessionKey=${staleGatewaySessionKey} jobId=${input.jobId ?? "(none)"}`
24564
24603
  );
@@ -24566,7 +24605,8 @@ var init_outbound_behavior = __esm({
24566
24605
  userContent: input.userContent,
24567
24606
  llmContent: input.llmContent,
24568
24607
  ...input.jobId ? { jobId: input.jobId } : {},
24569
- ...input.sessionKey ? { currentSessionKey: input.sessionKey } : {}
24608
+ ...input.sessionKey ? { currentSessionKey: input.sessionKey } : {},
24609
+ idempotencyKey: deliveryId
24570
24610
  });
24571
24611
  assertLatestUserFanoutDelivered("okx-a2a.prompt_user", result);
24572
24612
  this.persistDeliveredFallbackRoutes(input.jobId, result, { replaceExisting: true });
@@ -24708,7 +24748,7 @@ var init_sentry_config = __esm({
24708
24748
  environment = process.env.SENTRY_ENV === "dev" ? "dev" : "prod";
24709
24749
  SENTRY_CONFIG = {
24710
24750
  projectName: "okx/openclaw-okx-a2a-extension",
24711
- release: "0.0.17",
24751
+ release: "0.0.18-beta-8614cb2a91-260625165344",
24712
24752
  environment
24713
24753
  };
24714
24754
  }
@@ -70552,10 +70592,10 @@ var init_secp256k1 = __esm({
70552
70592
 
70553
70593
  // ../../node_modules/@xmtp/content-type-remote-attachment/dist/index.js
70554
70594
  async function encrypt(plain, secret, additionalData) {
70555
- const salt = import_node_crypto5.webcrypto.getRandomValues(new Uint8Array(KDFSaltSize));
70556
- const nonce = import_node_crypto5.webcrypto.getRandomValues(new Uint8Array(AESGCMNonceSize));
70595
+ const salt = import_node_crypto6.webcrypto.getRandomValues(new Uint8Array(KDFSaltSize));
70596
+ const nonce = import_node_crypto6.webcrypto.getRandomValues(new Uint8Array(AESGCMNonceSize));
70557
70597
  const key = await hkdf(secret, salt);
70558
- const encrypted = await import_node_crypto5.webcrypto.subtle.encrypt(aesGcmParams(nonce), key, plain);
70598
+ const encrypted = await import_node_crypto6.webcrypto.subtle.encrypt(aesGcmParams(nonce), key, plain);
70559
70599
  return new Ciphertext({
70560
70600
  aes256GcmHkdfSha256: {
70561
70601
  payload: new Uint8Array(encrypted),
@@ -70569,7 +70609,7 @@ async function decrypt(encrypted, secret, additionalData) {
70569
70609
  throw new Error("invalid payload ciphertext");
70570
70610
  }
70571
70611
  const key = await hkdf(secret, encrypted.aes256GcmHkdfSha256.hkdfSalt);
70572
- const decrypted = await import_node_crypto5.webcrypto.subtle.decrypt(aesGcmParams(encrypted.aes256GcmHkdfSha256.gcmNonce), key, encrypted.aes256GcmHkdfSha256.payload);
70612
+ const decrypted = await import_node_crypto6.webcrypto.subtle.decrypt(aesGcmParams(encrypted.aes256GcmHkdfSha256.gcmNonce), key, encrypted.aes256GcmHkdfSha256.payload);
70573
70613
  return new Uint8Array(decrypted);
70574
70614
  }
70575
70615
  function aesGcmParams(nonce, additionalData) {
@@ -70580,18 +70620,18 @@ function aesGcmParams(nonce, additionalData) {
70580
70620
  return spec;
70581
70621
  }
70582
70622
  async function hkdf(secret, salt) {
70583
- const key = await import_node_crypto5.webcrypto.subtle.importKey("raw", secret, "HKDF", false, [
70623
+ const key = await import_node_crypto6.webcrypto.subtle.importKey("raw", secret, "HKDF", false, [
70584
70624
  "deriveKey"
70585
70625
  ]);
70586
- return import_node_crypto5.webcrypto.subtle.deriveKey({ name: "HKDF", hash: "SHA-256", salt, info: hkdfNoInfo }, key, { name: "AES-GCM", length: 256 }, false, ["encrypt", "decrypt"]);
70626
+ return import_node_crypto6.webcrypto.subtle.deriveKey({ name: "HKDF", hash: "SHA-256", salt, info: hkdfNoInfo }, key, { name: "AES-GCM", length: 256 }, false, ["encrypt", "decrypt"]);
70587
70627
  }
70588
- var import_proto2, import_node_crypto5, ContentTypeAttachment, AttachmentCodec, KDFSaltSize, AESGCMNonceSize, AESGCMTagLength, Ciphertext, hkdfNoInfo, ContentTypeRemoteAttachment, RemoteAttachmentCodec;
70628
+ var import_proto2, import_node_crypto6, ContentTypeAttachment, AttachmentCodec, KDFSaltSize, AESGCMNonceSize, AESGCMTagLength, Ciphertext, hkdfNoInfo, ContentTypeRemoteAttachment, RemoteAttachmentCodec;
70589
70629
  var init_dist6 = __esm({
70590
70630
  "../../node_modules/@xmtp/content-type-remote-attachment/dist/index.js"() {
70591
70631
  init_dist();
70592
70632
  init_secp256k1();
70593
70633
  import_proto2 = __toESM(require_node3(), 1);
70594
- import_node_crypto5 = require("node:crypto");
70634
+ import_node_crypto6 = require("node:crypto");
70595
70635
  ContentTypeAttachment = new ContentTypeId({
70596
70636
  authorityId: "xmtp.org",
70597
70637
  typeId: "attachment",
@@ -70671,7 +70711,7 @@ var init_dist6 = __esm({
70671
70711
  if (payload.length === 0) {
70672
70712
  throw new Error(`no payload for remote attachment at ${remoteAttachment.url}`);
70673
70713
  }
70674
- const digestBytes = new Uint8Array(await import_node_crypto5.webcrypto.subtle.digest("SHA-256", payload));
70714
+ const digestBytes = new Uint8Array(await import_node_crypto6.webcrypto.subtle.digest("SHA-256", payload));
70675
70715
  const digest2 = etc.bytesToHex(digestBytes);
70676
70716
  if (digest2 !== remoteAttachment.contentDigest) {
70677
70717
  throw new Error("content digest does not match");
@@ -70695,7 +70735,7 @@ var init_dist6 = __esm({
70695
70735
  return codec.decode(encodedContent, codecRegistry);
70696
70736
  }
70697
70737
  static async encodeEncrypted(content$1, codec) {
70698
- const secret = import_node_crypto5.webcrypto.getRandomValues(new Uint8Array(32));
70738
+ const secret = import_node_crypto6.webcrypto.getRandomValues(new Uint8Array(32));
70699
70739
  const encodedContent = import_proto2.content.EncodedContent.encode(codec.encode(content$1, {
70700
70740
  codecFor() {
70701
70741
  return void 0;
@@ -70708,7 +70748,7 @@ var init_dist6 = __esm({
70708
70748
  if (!salt || !nonce || !payload) {
70709
70749
  throw new Error("missing encryption key");
70710
70750
  }
70711
- const digestBytes = new Uint8Array(await import_node_crypto5.webcrypto.subtle.digest("SHA-256", payload));
70751
+ const digestBytes = new Uint8Array(await import_node_crypto6.webcrypto.subtle.digest("SHA-256", payload));
70712
70752
  const digest2 = etc.bytesToHex(digestBytes);
70713
70753
  return {
70714
70754
  digest: digest2,
@@ -86737,14 +86777,14 @@ function buildSystemMessageIdempotencyKey(input) {
86737
86777
  return `system-message:${identity3}`;
86738
86778
  }
86739
86779
  function stableHash(value) {
86740
- return (0, import_node_crypto6.createHash)("sha256").update(value).digest("hex").slice(0, 24);
86780
+ return (0, import_node_crypto7.createHash)("sha256").update(value).digest("hex").slice(0, 24);
86741
86781
  }
86742
- var import_node_crypto6, DIRECTION_PREFIX, CONTENT_SEPARATOR, ADDRESS_SHORT_HEAD, ADDRESS_SHORT_TAIL, JOB_ID_HEAD, JOB_ID_TAIL, ELLIPSIS, CONTENT_MAX_LINES;
86782
+ var import_node_crypto7, DIRECTION_PREFIX, CONTENT_SEPARATOR, ADDRESS_SHORT_HEAD, ADDRESS_SHORT_TAIL, JOB_ID_HEAD, JOB_ID_TAIL, ELLIPSIS, CONTENT_MAX_LINES;
86743
86783
  var init_agent_message_notice = __esm({
86744
86784
  "src/agent-message-notice.ts"() {
86745
86785
  "use strict";
86746
86786
  init_log();
86747
- import_node_crypto6 = require("node:crypto");
86787
+ import_node_crypto7 = require("node:crypto");
86748
86788
  init_session_store();
86749
86789
  init_ai_provider();
86750
86790
  init_outbound_behavior();
@@ -87266,7 +87306,7 @@ async function handleSqliteGroupSendCommand(params) {
87266
87306
  });
87267
87307
  logWithTimestamp(`[okx-agent-task] xmtp envelope ${rawText}`);
87268
87308
  await conversation.send(rawText);
87269
- const messageId = `outbound-${(0, import_node_crypto7.randomUUID)()}`;
87309
+ const messageId = `outbound-${(0, import_node_crypto8.randomUUID)()}`;
87270
87310
  await notifyAgentMessageToUserAttention({
87271
87311
  direction: "outbound" /* OUTBOUND */,
87272
87312
  sender: {
@@ -87404,7 +87444,7 @@ async function handleGroupSendCommand(params) {
87404
87444
  logWithTimestamp(`[okx-agent-task] xmtp envelope ${rawText}`);
87405
87445
  await conversation.send(rawText);
87406
87446
  const now = Date.now();
87407
- const messageId = `outbound-${(0, import_node_crypto7.randomUUID)()}`;
87447
+ const messageId = `outbound-${(0, import_node_crypto8.randomUUID)()}`;
87408
87448
  const stored = {
87409
87449
  id: messageId,
87410
87450
  direction: "outbound",
@@ -87613,7 +87653,7 @@ async function handleXmtpSendCommand(params) {
87613
87653
  const rawText = target.chatType === "group" ? buildGroupReplyRaw(command, target, target.myXmtpAddress, localAgent) : buildDmReplyRaw(command, target, localAgent?.agentId ?? null);
87614
87654
  await conversation.send(rawText);
87615
87655
  const now = Date.now();
87616
- const messageId = `outbound-${(0, import_node_crypto7.randomUUID)()}`;
87656
+ const messageId = `outbound-${(0, import_node_crypto8.randomUUID)()}`;
87617
87657
  const stored = {
87618
87658
  id: messageId,
87619
87659
  direction: "outbound",
@@ -87659,12 +87699,12 @@ async function handleXmtpSendCommand(params) {
87659
87699
  ownedStore?.close();
87660
87700
  }
87661
87701
  }
87662
- var import_node_crypto7, TASK_MIN_VERSION, sqliteGroupSessionPromises, resolvedAgentByIdCache, resolvedAgentByAddressCache;
87702
+ var import_node_crypto8, TASK_MIN_VERSION, sqliteGroupSessionPromises, resolvedAgentByIdCache, resolvedAgentByAddressCache;
87663
87703
  var init_xmtp_send = __esm({
87664
87704
  "src/xmtp-send.ts"() {
87665
87705
  "use strict";
87666
87706
  init_log();
87667
- import_node_crypto7 = require("node:crypto");
87707
+ import_node_crypto8 = require("node:crypto");
87668
87708
  init_dist4();
87669
87709
  init_envelope();
87670
87710
  init_concurrency2();
@@ -89363,7 +89403,7 @@ function normalizeAttentionProvider(provider) {
89363
89403
  return provider === "unknown" ? null : provider;
89364
89404
  }
89365
89405
  function stableHash2(value) {
89366
- return (0, import_node_crypto8.createHash)("sha256").update(value).digest("hex").slice(0, 24);
89406
+ return (0, import_node_crypto9.createHash)("sha256").update(value).digest("hex").slice(0, 24);
89367
89407
  }
89368
89408
  function formatCommand(args) {
89369
89409
  return args.map(shellQuote).join(" ");
@@ -89387,12 +89427,12 @@ function shortenJobId2(jobId) {
89387
89427
  }
89388
89428
  return `${jobId.slice(0, 6)}\u2026${jobId.slice(-4)}`;
89389
89429
  }
89390
- var import_node_crypto8, import_node_fs14, import_promises6, import_node_child_process6, import_node_os6, import_node_path18, AiRunner, CODEX_TOOL_FAILURE_MARKER;
89430
+ var import_node_crypto9, import_node_fs14, import_promises6, import_node_child_process6, import_node_os6, import_node_path18, AiRunner, CODEX_TOOL_FAILURE_MARKER;
89391
89431
  var init_ai_runner = __esm({
89392
89432
  "src/ai-runner.ts"() {
89393
89433
  "use strict";
89394
89434
  init_log();
89395
- import_node_crypto8 = require("node:crypto");
89435
+ import_node_crypto9 = require("node:crypto");
89396
89436
  import_node_fs14 = require("node:fs");
89397
89437
  import_promises6 = require("node:fs/promises");
89398
89438
  import_node_child_process6 = require("node:child_process");
@@ -91627,7 +91667,7 @@ async function processFileMessage(ctx, deps, options = {}) {
91627
91667
  timing.mark("payloadParse", parseStartedAt);
91628
91668
  const systemNotification = chatType === "dm" && parsed.parsed ? extractSystemNotification(parsed.payload) : null;
91629
91669
  if (systemNotification) {
91630
- const systemMessageId = messageId || `system-${(0, import_node_crypto9.randomUUID)()}`;
91670
+ const systemMessageId = messageId || `system-${(0, import_node_crypto10.randomUUID)()}`;
91631
91671
  if (!systemNotification.agentId) {
91632
91672
  logger.error(
91633
91673
  LogEvent.INBOUND_DROP_DM_INVALID_PAYLOAD,
@@ -91829,7 +91869,7 @@ async function processFileMessage(ctx, deps, options = {}) {
91829
91869
  toAgentId
91830
91870
  });
91831
91871
  const existingSession = deps.sessionStore?.getSession(sessionKey) ?? null;
91832
- const routedMessageId = messageId || `group-${(0, import_node_crypto9.randomUUID)()}`;
91872
+ const routedMessageId = messageId || `group-${(0, import_node_crypto10.randomUUID)()}`;
91833
91873
  const consentState = ctx.conversation instanceof Group ? ctx.conversation.consentState : void 0;
91834
91874
  if (shouldKeepInboundGroupPendingForBuyer({
91835
91875
  consentState,
@@ -91922,7 +91962,7 @@ async function processFileMessage(ctx, deps, options = {}) {
91922
91962
  return true;
91923
91963
  }
91924
91964
  const stored = {
91925
- id: messageId || `local-${(0, import_node_crypto9.randomUUID)()}`,
91965
+ id: messageId || `local-${(0, import_node_crypto10.randomUUID)()}`,
91926
91966
  direction: "inbound",
91927
91967
  route: route.route,
91928
91968
  routeReason: route.routeReason,
@@ -92058,7 +92098,7 @@ function processOfflineFromCoreDeps(store, ctx, deps, options) {
92058
92098
  function buildSystemStoredMessage(params) {
92059
92099
  const now = Date.now();
92060
92100
  return {
92061
- id: params.id ?? `system-${now}-${(0, import_node_crypto9.randomUUID)()}`,
92101
+ id: params.id ?? `system-${now}-${(0, import_node_crypto10.randomUUID)()}`,
92062
92102
  direction: "system",
92063
92103
  route: "backup",
92064
92104
  routeReason: params.reason,
@@ -92076,12 +92116,12 @@ function buildSystemStoredMessage(params) {
92076
92116
  function isA2AEnvelope(payload) {
92077
92117
  return isPlainObject3(payload) && payload.msgType === A2A_MESSAGE_TYPE;
92078
92118
  }
92079
- var import_node_crypto9, PROCESSED_IDS_MAX, processedMessageIds;
92119
+ var import_node_crypto10, PROCESSED_IDS_MAX, processedMessageIds;
92080
92120
  var init_message_handler = __esm({
92081
92121
  "src/message-handler.ts"() {
92082
92122
  "use strict";
92083
92123
  init_log();
92084
- import_node_crypto9 = require("node:crypto");
92124
+ import_node_crypto10 = require("node:crypto");
92085
92125
  init_dist4();
92086
92126
  init_a2a();
92087
92127
  init_xmtp_sdk();
@@ -92137,7 +92177,7 @@ function isOriginalParentProcessAlive(options) {
92137
92177
  }
92138
92178
  function registerUserAttentionWatcher(options) {
92139
92179
  return options.store.registerUserAttentionWatcher({
92140
- id: options.id ?? (0, import_node_crypto10.randomUUID)(),
92180
+ id: options.id ?? (0, import_node_crypto11.randomUUID)(),
92141
92181
  provider: options.provider,
92142
92182
  jobId: options.jobId,
92143
92183
  nowMs: options.nowMs ?? Date.now(),
@@ -92216,11 +92256,11 @@ function userWatchEventDeliveredSentryExtra(event) {
92216
92256
  hasDecision: String(event.hasDecision)
92217
92257
  };
92218
92258
  }
92219
- var import_node_crypto10, USER_ATTENTION_WATCH_REPLACED_MESSAGE, USER_ATTENTION_WATCHER_SCAN_MS, USER_ATTENTION_WATCHER_TTL_MS, USER_ATTENTION_WATCH_PARENT_CHECK_MS;
92259
+ var import_node_crypto11, USER_ATTENTION_WATCH_REPLACED_MESSAGE, USER_ATTENTION_WATCHER_SCAN_MS, USER_ATTENTION_WATCHER_TTL_MS, USER_ATTENTION_WATCH_PARENT_CHECK_MS;
92220
92260
  var init_user_attention_watchers = __esm({
92221
92261
  "src/user-attention-watchers.ts"() {
92222
92262
  "use strict";
92223
- import_node_crypto10 = require("node:crypto");
92263
+ import_node_crypto11 = require("node:crypto");
92224
92264
  init_sentry_logger();
92225
92265
  USER_ATTENTION_WATCH_REPLACED_MESSAGE = "Another okx-a2a user watch with the same job scope was started, so this watcher has been closed. Do not run this watch command again automatically, because starting another watcher may interrupt a different session that is already monitoring task progress.";
92226
92266
  USER_ATTENTION_WATCHER_SCAN_MS = 500;
@@ -92460,12 +92500,12 @@ async function runListenerWithLock(options, paths) {
92460
92500
  }));
92461
92501
  }
92462
92502
  });
92463
- service.setPluginVersion("0.0.17");
92503
+ service.setPluginVersion("0.0.18-beta-8614cb2a91-260625165344");
92464
92504
  await service.init();
92465
92505
  const pluginVersionStatus = service.pluginVersionStatus;
92466
92506
  if (pluginVersionStatus.unavailable) {
92467
92507
  throw new Error(
92468
- `@okxweb3/a2a-node v${"0.0.17"} is below the required minimum v${pluginVersionStatus.minVersion}`
92508
+ `@okxweb3/a2a-node v${"0.0.18-beta-8614cb2a91-260625165344"} is below the required minimum v${pluginVersionStatus.minVersion}`
92469
92509
  );
92470
92510
  }
92471
92511
  const systemConfig = service.getSystemConfig();
@@ -92483,7 +92523,7 @@ async function runListenerWithLock(options, paths) {
92483
92523
  onchainosAgentId: "*",
92484
92524
  reason: "system-config missing sentryDsn",
92485
92525
  pluginId: "@okxweb3/a2a-node",
92486
- pluginVersion: "0.0.17"
92526
+ pluginVersion: "0.0.18-beta-8614cb2a91-260625165344"
92487
92527
  });
92488
92528
  }
92489
92529
  logWithTimestamp(
@@ -93012,7 +93052,7 @@ async function uploadFile(params) {
93012
93052
  const attachment = { filename, mimeType, data: new Uint8Array(data) };
93013
93053
  const encrypted = await RemoteAttachmentCodec.encodeEncrypted(attachment, new AttachmentCodec());
93014
93054
  ensureFileDirs();
93015
- const encryptedPath = (0, import_node_path21.resolve)(FILE_WORK_DIR, `${(0, import_node_crypto11.randomUUID)()}.enc`);
93055
+ const encryptedPath = (0, import_node_path21.resolve)(FILE_WORK_DIR, `${(0, import_node_crypto12.randomUUID)()}.enc`);
93016
93056
  (0, import_node_fs17.writeFileSync)(encryptedPath, encrypted.payload);
93017
93057
  try {
93018
93058
  const stdout = runOnchainos([
@@ -93056,7 +93096,7 @@ async function uploadFile(params) {
93056
93096
  }
93057
93097
  async function downloadFile(params) {
93058
93098
  ensureFileDirs();
93059
- const encryptedPath = (0, import_node_path21.resolve)(FILE_WORK_DIR, `${(0, import_node_crypto11.randomUUID)()}.enc`);
93099
+ const encryptedPath = (0, import_node_path21.resolve)(FILE_WORK_DIR, `${(0, import_node_crypto12.randomUUID)()}.enc`);
93060
93100
  try {
93061
93101
  const stdout = runOnchainos([
93062
93102
  "agent",
@@ -93081,7 +93121,7 @@ async function downloadFile(params) {
93081
93121
  throw new Error(`file download failed: ${stdout}`);
93082
93122
  }
93083
93123
  const payload = new Uint8Array((0, import_node_fs17.readFileSync)(encryptedPath));
93084
- const digestBytes = new Uint8Array(await import_node_crypto11.webcrypto.subtle.digest("SHA-256", payload));
93124
+ const digestBytes = new Uint8Array(await import_node_crypto12.webcrypto.subtle.digest("SHA-256", payload));
93085
93125
  const actualDigest = Array.from(digestBytes).map((byte) => byte.toString(16).padStart(2, "0")).join("");
93086
93126
  if (actualDigest !== params.digest) {
93087
93127
  throw new Error(`file download digest verification failed: expected=${params.digest}, actual=${actualDigest}`);
@@ -93089,7 +93129,7 @@ async function downloadFile(params) {
93089
93129
  const decryptedBytes = await decryptAttachmentPayload(payload, params);
93090
93130
  const encodedContent = import_proto4.content.EncodedContent.decode(decryptedBytes);
93091
93131
  const attachment = new AttachmentCodec().decode(encodedContent);
93092
- const outputFilename = params.filename || attachment.filename || `${(0, import_node_crypto11.randomUUID)()}.bin`;
93132
+ const outputFilename = params.filename || attachment.filename || `${(0, import_node_crypto12.randomUUID)()}.bin`;
93093
93133
  const outputDir = DOWNLOADS_DIR;
93094
93134
  ensureA2aTaskDir(outputDir);
93095
93135
  const outputPath = (0, import_node_path21.resolve)(outputDir, (0, import_node_path21.basename)(outputFilename));
@@ -93106,15 +93146,15 @@ async function decryptAttachmentPayload(payload, params) {
93106
93146
  const secretBytes = new Uint8Array(Buffer.from(params.secret, "base64"));
93107
93147
  const saltBytes = new Uint8Array(Buffer.from(params.salt, "base64"));
93108
93148
  const nonceBytes = new Uint8Array(Buffer.from(params.nonce, "base64"));
93109
- const hkdfKey = await import_node_crypto11.webcrypto.subtle.importKey("raw", secretBytes, "HKDF", false, ["deriveKey"]);
93110
- const aesKey = await import_node_crypto11.webcrypto.subtle.deriveKey(
93149
+ const hkdfKey = await import_node_crypto12.webcrypto.subtle.importKey("raw", secretBytes, "HKDF", false, ["deriveKey"]);
93150
+ const aesKey = await import_node_crypto12.webcrypto.subtle.deriveKey(
93111
93151
  { name: "HKDF", hash: "SHA-256", salt: saltBytes, info: new Uint8Array().buffer },
93112
93152
  hkdfKey,
93113
93153
  { name: "AES-GCM", length: 256 },
93114
93154
  false,
93115
93155
  ["decrypt"]
93116
93156
  );
93117
- return new Uint8Array(await import_node_crypto11.webcrypto.subtle.decrypt({ name: "AES-GCM", iv: nonceBytes }, aesKey, toArrayBuffer(payload)));
93157
+ return new Uint8Array(await import_node_crypto12.webcrypto.subtle.decrypt({ name: "AES-GCM", iv: nonceBytes }, aesKey, toArrayBuffer(payload)));
93118
93158
  }
93119
93159
  function toArrayBuffer(bytes) {
93120
93160
  return bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength);
@@ -93253,12 +93293,12 @@ function readRequiredOption(args, name2) {
93253
93293
  }
93254
93294
  return value;
93255
93295
  }
93256
- var import_node_child_process7, import_node_crypto11, import_node_fs17, import_node_path21, import_proto4, OKX_A2A_PATHS, OKX_A2A_HOME_DIR, FILE_WORK_DIR, DOWNLOADS_DIR, SYSTEM_CONFIG_PATH;
93296
+ var import_node_child_process7, import_node_crypto12, import_node_fs17, import_node_path21, import_proto4, OKX_A2A_PATHS, OKX_A2A_HOME_DIR, FILE_WORK_DIR, DOWNLOADS_DIR, SYSTEM_CONFIG_PATH;
93257
93297
  var init_file_cli = __esm({
93258
93298
  "src/file-cli.ts"() {
93259
93299
  "use strict";
93260
93300
  import_node_child_process7 = require("node:child_process");
93261
- import_node_crypto11 = require("node:crypto");
93301
+ import_node_crypto12 = require("node:crypto");
93262
93302
  import_node_fs17 = require("node:fs");
93263
93303
  import_node_path21 = require("node:path");
93264
93304
  init_dist6();
@@ -93281,12 +93321,29 @@ __export(user_attention_cli_exports, {
93281
93321
  handleUserCommand: () => handleUserCommand
93282
93322
  });
93283
93323
  async function handleUserCommand(args) {
93284
- if (hasHelpFlag2(args)) {
93324
+ const subcommand = args[0];
93325
+ if (!subcommand || args.every(isHelpArg)) {
93285
93326
  printUserUsage();
93286
93327
  return;
93287
93328
  }
93329
+ if (subcommand === "help") {
93330
+ const helpTarget = args.slice(1).find((arg) => !isHelpArg(arg));
93331
+ if (!helpTarget) {
93332
+ printUserUsage();
93333
+ return;
93334
+ }
93335
+ if (!printUserSubcommandUsage(helpTarget)) {
93336
+ throw new Error(`Unknown user command: ${helpTarget}`);
93337
+ }
93338
+ return;
93339
+ }
93340
+ if (hasHelpFlag2(args.slice(1))) {
93341
+ if (!printUserSubcommandUsage(subcommand)) {
93342
+ throw new Error(`Unknown user command: ${subcommand}`);
93343
+ }
93344
+ return;
93345
+ }
93288
93346
  const commandStartedAt = Date.now();
93289
- const subcommand = args[0];
93290
93347
  const parsed = parseArgs(args.slice(1));
93291
93348
  const json = parsed.flags.has("json");
93292
93349
  const storeInitStartedAt = Date.now();
@@ -93295,15 +93352,12 @@ async function handleUserCommand(args) {
93295
93352
  let usedOpenClawGateway = false;
93296
93353
  let quietUserAttentionConsole = false;
93297
93354
  try {
93298
- if (!subcommand || subcommand === "help" || parsed.flags.has("help")) {
93299
- printUserUsage();
93300
- return;
93301
- }
93302
93355
  if (subcommand === "notify") {
93303
93356
  quietUserAttentionConsole = true;
93304
93357
  assertNoUserSessionKey(parsed, subcommand);
93305
93358
  const jobId = readJobId(parsed);
93306
93359
  const provider = resolveUserAttentionProvider(store, jobId);
93360
+ const expireTime = provider === "openclaw" ? null : readExpireTime(parsed);
93307
93361
  const behavior = createOutboundBehavior(provider, { store });
93308
93362
  usedOpenClawGateway = provider === "openclaw";
93309
93363
  const sessionKey = readCurrentSessionKeyFromEnv();
@@ -93313,7 +93367,8 @@ async function handleUserCommand(args) {
93313
93367
  userContent: readRequiredOption2(parsed, "content"),
93314
93368
  jobId,
93315
93369
  sessionKey,
93316
- idempotencyKey: parsed.options.get("idempotency-key") ?? null
93370
+ idempotencyKey: parsed.options.get("idempotency-key") ?? null,
93371
+ expireTime
93317
93372
  });
93318
93373
  });
93319
93374
  outputOk();
@@ -93324,6 +93379,7 @@ async function handleUserCommand(args) {
93324
93379
  assertNoUserSessionKey(parsed, subcommand);
93325
93380
  const jobId = readJobId(parsed);
93326
93381
  const provider = resolveUserAttentionProvider(store, jobId);
93382
+ const expireTime = provider === "openclaw" ? null : readExpireTime(parsed);
93327
93383
  const behavior = createOutboundBehavior(provider, { store });
93328
93384
  usedOpenClawGateway = provider === "openclaw";
93329
93385
  const sessionKey = readCurrentSessionKeyFromEnv();
@@ -93334,7 +93390,8 @@ async function handleUserCommand(args) {
93334
93390
  llmContent: readRequiredOption2(parsed, "llm-content"),
93335
93391
  jobId,
93336
93392
  sessionKey,
93337
- idempotencyKey: parsed.options.get("idempotency-key") ?? null
93393
+ idempotencyKey: parsed.options.get("idempotency-key") ?? null,
93394
+ expireTime
93338
93395
  });
93339
93396
  });
93340
93397
  outputOk();
@@ -93402,14 +93459,17 @@ async function handleUserCommand(args) {
93402
93459
  }
93403
93460
  }
93404
93461
  function hasHelpFlag2(args) {
93405
- return args.some((arg) => arg === "-h" || arg === "--help" || arg === "help");
93462
+ return args.some((arg) => arg === "-h" || arg === "--help");
93463
+ }
93464
+ function isHelpArg(arg) {
93465
+ return arg === "-h" || arg === "--help" || arg === "help";
93406
93466
  }
93407
93467
  function printUserUsage() {
93408
93468
  console.log(`Usage: okx-a2a user <notify|decision-request|list|outdated-list|consume|check|watch>
93409
93469
 
93410
93470
  Commands:
93411
- notify --content <text> [--job-id <id>] [--idempotency-key <key>] [--json]
93412
- decision-request --user-content <text> --llm-content <text> [--job-id <id>] [--idempotency-key <key>] [--json]
93471
+ notify --content <text> [--job-id <id>] [--idempotency-key <key>] [--expire-time <unixSeconds>] [--json]
93472
+ decision-request --user-content <text> --llm-content <text> [--job-id <id>] [--idempotency-key <key>] [--expire-time <unixSeconds>] [--json]
93413
93473
  list [--include-handled] [--provider <provider>|--all-providers] [--job-id <id>] [--limit <n>] [--json]
93414
93474
  outdated-list [--provider <provider>|--all-providers]
93415
93475
  consume [--provider <provider>|--all-providers] [--job-id <id>] [--json]
@@ -93417,6 +93477,87 @@ Commands:
93417
93477
  watch [--once] [--json] [--provider <provider>|--all-providers] [--job-id <id>] [--timeout <seconds>] [--poll-ms <ms>] [--ignore-daemon-status]
93418
93478
  `);
93419
93479
  }
93480
+ function printUserSubcommandUsage(subcommand) {
93481
+ switch (subcommand) {
93482
+ case "notify":
93483
+ console.log(`Usage: okx-a2a user notify --content <text> [options]
93484
+
93485
+ Options:
93486
+ --content <text> Notification text shown to the user.
93487
+ --job-id <id> Bind the notification to a job.
93488
+ --idempotency-key <key> Reuse an existing notification for duplicate sends.
93489
+ --expire-time <unixSeconds> Ignore the notification after this absolute Unix timestamp in seconds.
93490
+ --json Emit machine-readable JSON output.
93491
+ `);
93492
+ return true;
93493
+ case "decision-request":
93494
+ console.log(`Usage: okx-a2a user decision-request --user-content <text> --llm-content <text> [options]
93495
+
93496
+ Options:
93497
+ --user-content <text> Decision prompt shown to the user.
93498
+ --llm-content <text> Context/instructions for the AI side of the decision.
93499
+ --job-id <id> Bind the decision request to a job.
93500
+ --idempotency-key <key> Reuse an existing decision request for duplicate sends.
93501
+ --expire-time <unixSeconds> Ignore the decision request after this absolute Unix timestamp in seconds.
93502
+ --json Emit machine-readable JSON output.
93503
+ `);
93504
+ return true;
93505
+ case "list":
93506
+ console.log(`Usage: okx-a2a user list [options]
93507
+
93508
+ Options:
93509
+ --include-handled Include already handled user attention records.
93510
+ --provider <provider> Filter by provider: codex, claude, hermes, or openclaw.
93511
+ --all-providers Do not filter by the current/provider-bound runtime.
93512
+ --job-id <id> Filter by job id.
93513
+ --limit <n> Maximum records to return. Defaults to 50.
93514
+ --json Emit machine-readable JSON output.
93515
+ `);
93516
+ return true;
93517
+ case "outdated-list":
93518
+ console.log(`Usage: okx-a2a user outdated-list [options]
93519
+
93520
+ Options:
93521
+ --provider <provider> Filter by provider: codex, claude, hermes, or openclaw.
93522
+ --all-providers Do not filter by the current/provider-bound runtime.
93523
+ `);
93524
+ return true;
93525
+ case "consume":
93526
+ console.log(`Usage: okx-a2a user consume [options]
93527
+
93528
+ Options:
93529
+ --provider <provider> Filter by provider: codex, claude, hermes, or openclaw.
93530
+ --all-providers Do not filter by the current/provider-bound runtime.
93531
+ --job-id <id> Drain records for a specific job.
93532
+ --json Emit machine-readable JSON output.
93533
+ `);
93534
+ return true;
93535
+ case "check":
93536
+ console.log(`Usage: okx-a2a user check --todo-ids <id,id> [options]
93537
+
93538
+ Options:
93539
+ --todo-ids <id,id> Comma-separated user attention ids to mark handled.
93540
+ --json Emit machine-readable JSON output.
93541
+ `);
93542
+ return true;
93543
+ case "watch":
93544
+ console.log(`Usage: okx-a2a user watch [options]
93545
+
93546
+ Options:
93547
+ --once Exit after the first batch of user attention records.
93548
+ --provider <provider> Filter by provider: codex, claude, hermes, or openclaw.
93549
+ --all-providers Do not filter by the current/provider-bound runtime.
93550
+ --job-id <id> Watch records for a specific job.
93551
+ --timeout <seconds> Stop waiting after this many seconds.
93552
+ --poll-ms <ms> Polling interval when IPC wake is unavailable. Defaults to 500.
93553
+ --ignore-daemon-status Read SQLite directly without requiring a running daemon.
93554
+ --json Emit machine-readable JSON output.
93555
+ `);
93556
+ return true;
93557
+ default:
93558
+ return false;
93559
+ }
93560
+ }
93420
93561
  async function watchUserAttention(store, parsed, json) {
93421
93562
  if (parsed.flags.has("from-now")) {
93422
93563
  throw new Error("--from-now has been removed; user watch always returns existing pending items first");
@@ -93638,7 +93779,8 @@ function formatAttentionItem(item) {
93638
93779
  const scope = [
93639
93780
  item.provider ? `provider=${item.provider}` : void 0,
93640
93781
  item.jobId ? `job=${item.jobId}` : void 0,
93641
- item.sessionKey ? `session=${item.sessionKey}` : void 0
93782
+ item.sessionKey ? `session=${item.sessionKey}` : void 0,
93783
+ item.expireTime !== void 0 ? `expireTime=${item.expireTime}` : void 0
93642
93784
  ].filter(Boolean).join(" ");
93643
93785
  const prefix = ` ${item.id} ${item.kind} ${item.status}`;
93644
93786
  return `${prefix}${scope ? ` ${scope}` : ""}
@@ -93965,6 +94107,17 @@ function readNumberOption(parsed, name2) {
93965
94107
  }
93966
94108
  return value;
93967
94109
  }
94110
+ function readExpireTime(parsed) {
94111
+ const raw = parsed.options.get("expire-time") ?? parsed.options.get("expireTime");
94112
+ if (!raw) {
94113
+ return null;
94114
+ }
94115
+ const value = Number(raw);
94116
+ if (!Number.isSafeInteger(value) || value < 0) {
94117
+ throw new Error("--expire-time must be a non-negative integer Unix timestamp in seconds");
94118
+ }
94119
+ return value;
94120
+ }
93968
94121
  var init_user_attention_cli = __esm({
93969
94122
  "src/user-attention-cli.ts"() {
93970
94123
  "use strict";
@@ -93987,12 +94140,12 @@ __export(session_cli_exports, {
93987
94140
  });
93988
94141
  async function handleSessionCommand(args) {
93989
94142
  const subcommand = args[0];
93990
- if (!subcommand || args.every(isHelpArg)) {
94143
+ if (!subcommand || args.every(isHelpArg2)) {
93991
94144
  printSessionUsage();
93992
94145
  return;
93993
94146
  }
93994
94147
  if (subcommand === "help") {
93995
- const helpTarget = args.slice(1).find((arg) => !isHelpArg(arg));
94148
+ const helpTarget = args.slice(1).find((arg) => !isHelpArg2(arg));
93996
94149
  if (!helpTarget) {
93997
94150
  printSessionUsage();
93998
94151
  return;
@@ -94174,9 +94327,9 @@ async function handleSessionCommand(args) {
94174
94327
  }
94175
94328
  }
94176
94329
  function hasHelpFlag3(args) {
94177
- return args.some(isHelpArg);
94330
+ return args.some(isHelpArg2);
94178
94331
  }
94179
- function isHelpArg(arg) {
94332
+ function isHelpArg2(arg) {
94180
94333
  return arg === "-h" || arg === "--help" || arg === "help";
94181
94334
  }
94182
94335
  function printSessionUsage() {
@@ -95202,7 +95355,7 @@ function buildProviderMismatchWarning(target, provider) {
95202
95355
  ].join("\n");
95203
95356
  }
95204
95357
  async function handleUpdateCommand(args) {
95205
- if (args.some(isHelpArg2)) {
95358
+ if (args.some(isHelpArg3)) {
95206
95359
  printUpdateUsage();
95207
95360
  return;
95208
95361
  }
@@ -95245,7 +95398,7 @@ function resolveUpdateTarget(target) {
95245
95398
  return detectGatewayInvocation() ?? "node";
95246
95399
  }
95247
95400
  async function handleSetupCommand(args) {
95248
- if (args.some(isHelpArg2)) {
95401
+ if (args.some(isHelpArg3)) {
95249
95402
  printSetupUsage();
95250
95403
  return;
95251
95404
  }
@@ -95482,7 +95635,7 @@ async function getCurrentNodeCliVersion() {
95482
95635
  return await getGlobalNpmPackageVersion(UPDATE_PACKAGES.node) ?? getBundledNodeCliVersion();
95483
95636
  }
95484
95637
  function getBundledNodeCliVersion() {
95485
- return true ? "0.0.17" : null;
95638
+ return true ? "0.0.18-beta-8614cb2a91-260625165344" : null;
95486
95639
  }
95487
95640
  function readConfiguredAiProvider() {
95488
95641
  const explicit = process.env.OKX_AGENT_TASK_AI_CLI ?? process.env.OKX_A2A_AI_PROVIDER;
@@ -96102,7 +96255,7 @@ function readOption2(args, name2) {
96102
96255
  function hasFlag(args, name2) {
96103
96256
  return args.includes(name2);
96104
96257
  }
96105
- function isHelpArg2(value) {
96258
+ function isHelpArg3(value) {
96106
96259
  return value === "-h" || value === "--help" || value === "help";
96107
96260
  }
96108
96261
  function isSupportedRelease(value) {
@@ -96242,7 +96395,7 @@ init_sentry_logger();
96242
96395
  init_sentry_config();
96243
96396
  var CURRENT_GATEWAY_SESSION_KEYS_ENV2 = "OKX_A2A_CURRENT_GATEWAY_SESSION_KEYS";
96244
96397
  function printUsage2() {
96245
- console.log(`okx-a2a ${"0.0.17"}
96398
+ console.log(`okx-a2a ${"0.0.18-beta-8614cb2a91-260625165344"}
96246
96399
 
96247
96400
  Usage:
96248
96401
  okx-a2a <command> [options]
@@ -96279,7 +96432,7 @@ Run \`okx-a2a <command> -h\` for command-specific help.
96279
96432
  `);
96280
96433
  }
96281
96434
  function printVersion() {
96282
- console.log("0.0.17");
96435
+ console.log("0.0.18-beta-8614cb2a91-260625165344");
96283
96436
  }
96284
96437
  function printDaemonUsage() {
96285
96438
  console.log(`Usage: okx-a2a daemon <start|restart|stop|status|autostart> [options]
@@ -96406,8 +96559,8 @@ function printUserUsageProxy() {
96406
96559
  console.log(`Usage: okx-a2a user <notify|decision-request|list|outdated-list|consume|check|watch>
96407
96560
 
96408
96561
  Commands:
96409
- notify --content <text> [--job-id <id>] [--idempotency-key <key>] [--json]
96410
- decision-request --user-content <text> --llm-content <text> [--job-id <id>] [--idempotency-key <key>] [--json]
96562
+ notify --content <text> [--job-id <id>] [--idempotency-key <key>] [--expire-time <unixSeconds>] [--json]
96563
+ decision-request --user-content <text> --llm-content <text> [--job-id <id>] [--idempotency-key <key>] [--expire-time <unixSeconds>] [--json]
96411
96564
  list [--include-handled] [--provider <provider>|--all-providers] [--job-id <id>] [--limit <n>] [--json]
96412
96565
  outdated-list [--provider <provider>|--all-providers]
96413
96566
  consume [--provider <provider>|--all-providers] [--job-id <id>] [--json]
@@ -96488,11 +96641,11 @@ Commands:
96488
96641
  Print setup status JSON to stdout. Installer logs are written to stderr.
96489
96642
  `);
96490
96643
  }
96491
- function isHelpArg3(value) {
96644
+ function isHelpArg4(value) {
96492
96645
  return value === "-h" || value === "--help" || value === "help";
96493
96646
  }
96494
96647
  function hasHelpFlag5(args) {
96495
- return args.some(isHelpArg3);
96648
+ return args.some(isHelpArg4);
96496
96649
  }
96497
96650
  function isVersionArg(value) {
96498
96651
  return value === "-v" || value === "--version" || value === "version";
@@ -97358,7 +97511,7 @@ async function main() {
97358
97511
  assertSupportedNodeVersion();
97359
97512
  const command = process.argv[2] ?? "status";
97360
97513
  const args = process.argv.slice(3);
97361
- if (isHelpArg3(command)) {
97514
+ if (isHelpArg4(command)) {
97362
97515
  printUsage2();
97363
97516
  return;
97364
97517
  }
@@ -97504,10 +97657,10 @@ async function main() {
97504
97657
  process.exitCode = 1;
97505
97658
  }
97506
97659
  function shouldDeferHelpToNestedHandler(command, args) {
97507
- if (command !== "session") {
97660
+ if (command !== "session" && command !== "user") {
97508
97661
  return false;
97509
97662
  }
97510
- return args.some((arg) => !isHelpArg3(arg));
97663
+ return args.some((arg) => !isHelpArg4(arg));
97511
97664
  }
97512
97665
  main().then(() => {
97513
97666
  if (cliSentryFlushTimedOut) {