@okxweb3/a2a-node 0.1.6 → 0.1.7

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 +234 -26
  2. package/dist/index.js +808 -556
  3. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -8300,7 +8300,7 @@ function buildConnectParams(config, instanceId, protocolVersion) {
8300
8300
  client: {
8301
8301
  id: "gateway-client",
8302
8302
  displayName: "okx-a2a-node",
8303
- version: "0.1.6",
8303
+ version: "0.1.7",
8304
8304
  platform: "node",
8305
8305
  mode: "backend",
8306
8306
  instanceId
@@ -8311,7 +8311,7 @@ function buildConnectParams(config, instanceId, protocolVersion) {
8311
8311
  commands: [],
8312
8312
  permissions: {},
8313
8313
  locale: Intl.DateTimeFormat().resolvedOptions().locale || "en-US",
8314
- userAgent: `okx-a2a-node/${"0.1.6"}`,
8314
+ userAgent: `okx-a2a-node/${"0.1.7"}`,
8315
8315
  auth: {
8316
8316
  ...config.token ? { token: config.token } : {},
8317
8317
  ...config.password ? { password: config.password } : {}
@@ -24344,6 +24344,7 @@ var init_events = __esm({
24344
24344
  SYSTEM_NOTIFICATION_RECEIVED: "System notification received",
24345
24345
  SYSTEM_NOTIFICATION_ROUTED: "System notification routed",
24346
24346
  HERMES_SESSION_ROUTE_BINDING: "Hermes session route binding",
24347
+ DOCTOR_REPORT: "Doctor report",
24347
24348
  // ── error ─────────────────────────────────────────────────────
24348
24349
  XMTP_CONNECTION_FAILED: "XMTP connection failed",
24349
24350
  CONVERSATIONS_STREAM_FAILED: "conversations.stream failed",
@@ -24383,6 +24384,8 @@ var init_events = __esm({
24383
24384
  DAEMON_LIFECYCLE_FAILED: "Daemon lifecycle failed",
24384
24385
  DAEMON_TICK_FAILED: "Daemon tick failed",
24385
24386
  DIRECT_CLI_FAILED: "Direct CLI failed",
24387
+ DOCTOR_NOT_READY: "Doctor not ready",
24388
+ DOCTOR_CRASHED: "Doctor crashed",
24386
24389
  AI_RUN_FAILED: "AI run failed",
24387
24390
  AI_RUN_TIMEOUT: "AI run timeout",
24388
24391
  AI_RUN_TOOL_FAILED: "AI run tool failed",
@@ -24406,7 +24409,8 @@ function agentExtras(identity3) {
24406
24409
  return {
24407
24410
  walletAddress: identity3.walletAddress || UNKNOWN_FIELD,
24408
24411
  inboxId: identity3.inboxId || UNKNOWN_FIELD,
24409
- onchainosAgentId: identity3.onchainosAgentId || UNKNOWN_FIELD
24412
+ onchainosAgentId: identity3.onchainosAgentId || UNKNOWN_FIELD,
24413
+ role: identity3.role != null && identity3.role !== "" ? String(identity3.role) : UNKNOWN_FIELD
24410
24414
  };
24411
24415
  }
24412
24416
  var Sentry, import_node_crypto4, FLOW_ID, SENTRY_EXTRA_BLOCKLIST, SENTRY_EXTRA_BLOCKED_KEY_PARTS, SENTRY_FULL_STRING_EXTRA_KEYS, SENTRY_TAG_KEYS, SENTRY_FINGERPRINT_KEYS, SENTRY_INFO_ALLOWLIST, MAX_EXTRA_STRING_LENGTH, MAX_TAG_VALUE_LENGTH, SentryLogger, logger, initLogger, shutdown, UNKNOWN_FIELD;
@@ -25561,16 +25565,17 @@ var init_task_config = __esm({
25561
25565
  });
25562
25566
 
25563
25567
  // ../core/src/sentry-config.ts
25564
- var environment, SENTRY_CONFIG;
25568
+ var environment, SENTRY_CONFIG, FALLBACK_SENTRY_DSN;
25565
25569
  var init_sentry_config = __esm({
25566
25570
  "../core/src/sentry-config.ts"() {
25567
25571
  "use strict";
25568
25572
  environment = process.env.SENTRY_ENV === "dev" ? "dev" : "prod";
25569
25573
  SENTRY_CONFIG = {
25570
25574
  projectName: "okx/openclaw-okx-a2a-extension",
25571
- release: "0.1.6",
25575
+ release: "0.1.7",
25572
25576
  environment
25573
25577
  };
25578
+ FALLBACK_SENTRY_DSN = "https://e20ff987c945887733de9ec6cca87aba@sentry.coinall.ltd/apmfe/70295";
25574
25579
  }
25575
25580
  });
25576
25581
 
@@ -86659,7 +86664,8 @@ var init_xmtp_sdk = __esm({
86659
86664
  const identity3 = {
86660
86665
  walletAddress: address,
86661
86666
  inboxId: agent.client?.inboxId,
86662
- onchainosAgentId: onchainosAgent?.agentId
86667
+ onchainosAgentId: onchainosAgent?.agentId,
86668
+ role: onchainosAgent?.role
86663
86669
  };
86664
86670
  try {
86665
86671
  await agent.client.conversations.syncAll([
@@ -86890,12 +86896,16 @@ var init_xmtp_sdk = __esm({
86890
86896
  ...agentExtras({
86891
86897
  walletAddress: address,
86892
86898
  inboxId: agent.client?.inboxId,
86893
- onchainosAgentId: this.getAgentByAddress(address)?.agentId
86899
+ onchainosAgentId: this.getAgentByAddress(address)?.agentId,
86900
+ role: this.getAgentByAddress(address)?.role
86894
86901
  }),
86895
86902
  ...jobIdExtras(msg.content),
86896
86903
  messageId: msg.id,
86897
86904
  conversationId: conv.id,
86898
- stage: "offlineReplay/handleMessage"
86905
+ stage: "offlineReplay/handleMessage",
86906
+ xmtpSentAtMs: String(msgSentMs),
86907
+ replayLagMs: String(Math.max(0, Date.now() - msgSentMs)),
86908
+ handleMs: String(handleMs)
86899
86909
  });
86900
86910
  } else {
86901
86911
  summary.skipped++;
@@ -88129,6 +88139,23 @@ var init_agent_message_notice = __esm({
88129
88139
  });
88130
88140
 
88131
88141
  // src/xmtp-send.ts
88142
+ function logXmtpMessageSent(params) {
88143
+ logger.info(LogEvent.MESSAGE_SENT, {
88144
+ component: params.component,
88145
+ stage: "outbound/xmtp_send",
88146
+ taskId: params.jobId,
88147
+ messageId: typeof params.xmtpMessageId === "string" && params.xmtpMessageId.length > 0 ? params.xmtpMessageId : "unknown",
88148
+ conversationId: params.conversationId,
88149
+ chatType: params.chatType,
88150
+ walletAddress: params.myXmtpAddress,
88151
+ toXmtpAddress: params.toXmtpAddress ?? "unknown",
88152
+ senderAgentId: params.senderAgentId ?? "unknown",
88153
+ toAgentId: params.toAgentId ?? "unknown",
88154
+ role: params.role != null && params.role !== "" ? String(params.role) : "unknown",
88155
+ xmtpSentAtMs: String(Date.now()),
88156
+ sendDurationMs: String(params.sendDurationMs)
88157
+ });
88158
+ }
88132
88159
  function isPlainObject(value) {
88133
88160
  return !!value && typeof value === "object" && !Array.isArray(value);
88134
88161
  }
@@ -88626,7 +88653,21 @@ async function handleSqliteGroupSendCommand(params) {
88626
88653
  payload: resolveEnvelopePayload(command, command.replyToMessageId)
88627
88654
  });
88628
88655
  logWithTimestamp(`[okx-agent-task] xmtp envelope ${rawText}`);
88629
- await conversation.send(rawText);
88656
+ const sendStartMs = Date.now();
88657
+ const xmtpMessageId = await conversation.send(rawText);
88658
+ logXmtpMessageSent({
88659
+ xmtpMessageId,
88660
+ conversationId: conversation.id,
88661
+ jobId: command.jobId,
88662
+ chatType: "group",
88663
+ component: "node_xmtp_send",
88664
+ myXmtpAddress,
88665
+ toXmtpAddress: remote.toXmtpAddress,
88666
+ senderAgentId: senderAgent?.agentId ?? command.myAgentId,
88667
+ toAgentId: remote.remoteAgent?.agentId ?? remote.toAgentId ?? command.toAgentId,
88668
+ role: senderAgent?.role,
88669
+ sendDurationMs: Date.now() - sendStartMs
88670
+ });
88630
88671
  const messageId = `outbound-${(0, import_node_crypto8.randomUUID)()}`;
88631
88672
  await notifyAgentMessageToUserAttention({
88632
88673
  direction: "outbound" /* OUTBOUND */,
@@ -88763,7 +88804,21 @@ async function handleGroupSendCommand(params) {
88763
88804
  payload: resolveEnvelopePayload(command, command.replyToMessageId)
88764
88805
  });
88765
88806
  logWithTimestamp(`[okx-agent-task] xmtp envelope ${rawText}`);
88766
- await conversation.send(rawText);
88807
+ const sendStartMs = Date.now();
88808
+ const xmtpMessageId = await conversation.send(rawText);
88809
+ logXmtpMessageSent({
88810
+ xmtpMessageId,
88811
+ conversationId: session.xmtpGroupId,
88812
+ jobId: command.jobId,
88813
+ chatType: "group",
88814
+ component: "node_xmtp_send",
88815
+ myXmtpAddress: session.myXmtpAddress,
88816
+ toXmtpAddress: session.toXmtpAddress,
88817
+ senderAgentId: senderAgent?.agentId ?? session.myAgentId,
88818
+ toAgentId: remoteAgent?.agentId ?? session.toAgentId,
88819
+ role: senderAgent?.role,
88820
+ sendDurationMs: Date.now() - sendStartMs
88821
+ });
88767
88822
  const now = Date.now();
88768
88823
  const messageId = `outbound-${(0, import_node_crypto8.randomUUID)()}`;
88769
88824
  const stored = {
@@ -88972,7 +89027,20 @@ async function handleXmtpSendCommand(params) {
88972
89027
  }
88973
89028
  const localAgent = service.getAgentByAddress(target.myXmtpAddress);
88974
89029
  const rawText = target.chatType === "group" ? buildGroupReplyRaw(command, target, target.myXmtpAddress, localAgent) : buildDmReplyRaw(command, target, localAgent?.agentId ?? null);
88975
- await conversation.send(rawText);
89030
+ const sendStartMs = Date.now();
89031
+ const xmtpMessageId = await conversation.send(rawText);
89032
+ logXmtpMessageSent({
89033
+ xmtpMessageId,
89034
+ conversationId: target.conversationId,
89035
+ jobId: command.jobId,
89036
+ chatType: target.chatType,
89037
+ component: "node_xmtp_send",
89038
+ myXmtpAddress: target.myXmtpAddress,
89039
+ toXmtpAddress: target.senderAddress,
89040
+ senderAgentId: localAgent?.agentId,
89041
+ role: localAgent?.role,
89042
+ sendDurationMs: Date.now() - sendStartMs
89043
+ });
88976
89044
  const now = Date.now();
88977
89045
  const messageId = `outbound-${(0, import_node_crypto8.randomUUID)()}`;
88978
89046
  const stored = {
@@ -89025,6 +89093,7 @@ var init_xmtp_send = __esm({
89025
89093
  "src/xmtp-send.ts"() {
89026
89094
  "use strict";
89027
89095
  init_log();
89096
+ init_sentry_logger();
89028
89097
  import_node_crypto8 = require("node:crypto");
89029
89098
  init_dist4();
89030
89099
  init_envelope();
@@ -92125,7 +92194,21 @@ async function sendRejectContentToTarget(content3, target, params) {
92125
92194
  }
92126
92195
  });
92127
92196
  logWithTimestamp(`[okx-agent-task] task reject xmtp envelope ${rawText}`);
92128
- await conversation.send(rawText);
92197
+ const sendStartMs = Date.now();
92198
+ const xmtpMessageId = await conversation.send(rawText);
92199
+ logXmtpMessageSent({
92200
+ xmtpMessageId,
92201
+ conversationId: target.groupId,
92202
+ jobId,
92203
+ chatType: "group",
92204
+ component: "node_command_processor",
92205
+ myXmtpAddress: target.address,
92206
+ toXmtpAddress,
92207
+ senderAgentId: senderAgent?.agentId,
92208
+ toAgentId: receiverAgent?.agentId ?? target.toAgentId,
92209
+ role: senderAgent?.role,
92210
+ sendDurationMs: Date.now() - sendStartMs
92211
+ });
92129
92212
  }
92130
92213
  async function denyTargets(targets, params) {
92131
92214
  return await Promise.all(
@@ -93295,7 +93378,7 @@ async function processFileMessage(ctx, deps, options = {}) {
93295
93378
  if (!providerGate.allowed) {
93296
93379
  return true;
93297
93380
  }
93298
- logger.info(LogEvent.SYSTEM_NOTIFICATION_RECEIVED, {
93381
+ logger.info(LogEvent.SYSTEM_NOTIFICATION_RECEIVED, timing.extras({
93299
93382
  ...agentExtras({ walletAddress: deps.myXmtpAddress, onchainosAgentId: systemNotification.agentId }),
93300
93383
  taskId: systemNotification.jobId ?? "",
93301
93384
  agentId: systemNotification.agentId ?? "",
@@ -93304,10 +93387,11 @@ async function processFileMessage(ctx, deps, options = {}) {
93304
93387
  messageId: systemMessageId,
93305
93388
  systemEvent: systemNotification.event ?? "",
93306
93389
  stage: "inbound/system_notification_received",
93390
+ source: options.source ?? "live",
93307
93391
  isDirectCommunication: String(systemNotification.isDirectCommunication),
93308
93392
  providerBinding: providerGate.provider ?? "",
93309
93393
  providerBindingCreated: String(providerGate.created)
93310
- });
93394
+ }));
93311
93395
  const routeResolveStartedAt = Date.now();
93312
93396
  const targets = directTarget ? [{
93313
93397
  sessionKey: directTarget.sessionKey,
@@ -93323,7 +93407,7 @@ async function processFileMessage(ctx, deps, options = {}) {
93323
93407
  );
93324
93408
  }
93325
93409
  const primaryTarget = targets[0];
93326
- logger.info(LogEvent.SYSTEM_NOTIFICATION_ROUTED, {
93410
+ logger.info(LogEvent.SYSTEM_NOTIFICATION_ROUTED, timing.extras({
93327
93411
  ...agentExtras({ walletAddress: deps.myXmtpAddress, onchainosAgentId: systemNotification.agentId }),
93328
93412
  taskId: systemNotification.jobId ?? "",
93329
93413
  agentId: primaryTarget?.agentId ?? systemNotification.agentId ?? "",
@@ -93335,8 +93419,9 @@ async function processFileMessage(ctx, deps, options = {}) {
93335
93419
  targetCount: String(targets.length),
93336
93420
  systemEvent: systemNotification.event ?? "",
93337
93421
  stage: "inbound/system_notification_routed",
93422
+ source: options.source ?? "live",
93338
93423
  isDirectCommunication: String(systemNotification.isDirectCommunication)
93339
- });
93424
+ }));
93340
93425
  if (!options.skipNotify) {
93341
93426
  maybeNotifyInboundAgentMessage({
93342
93427
  deps,
@@ -93667,7 +93752,7 @@ function processOfflineFromCoreDeps(store, ctx, deps, options) {
93667
93752
  allowGroup: deps.allowGroup,
93668
93753
  onJobMessageStored: options.onJobMessageStored,
93669
93754
  onSessionMessage: options.onSessionMessage
93670
- }, options);
93755
+ }, { ...options, source: "replay" });
93671
93756
  }
93672
93757
  function buildSystemStoredMessage(params) {
93673
93758
  const now = Date.now();
@@ -94086,12 +94171,12 @@ async function runListenerWithLock(options, paths) {
94086
94171
  }));
94087
94172
  }
94088
94173
  });
94089
- service.setPluginVersion("0.1.6");
94174
+ service.setPluginVersion("0.1.7");
94090
94175
  await service.init();
94091
94176
  const pluginVersionStatus = service.pluginVersionStatus;
94092
94177
  if (pluginVersionStatus.unavailable) {
94093
94178
  throw new Error(
94094
- `@okxweb3/a2a-node v${"0.1.6"} is below the required minimum v${pluginVersionStatus.minVersion}`
94179
+ `@okxweb3/a2a-node v${"0.1.7"} is below the required minimum v${pluginVersionStatus.minVersion}`
94095
94180
  );
94096
94181
  }
94097
94182
  const systemConfig = service.getSystemConfig();
@@ -94109,7 +94194,7 @@ async function runListenerWithLock(options, paths) {
94109
94194
  onchainosAgentId: "*",
94110
94195
  reason: "system-config missing sentryDsn",
94111
94196
  pluginId: "@okxweb3/a2a-node",
94112
- pluginVersion: "0.1.6"
94197
+ pluginVersion: "0.1.7"
94113
94198
  });
94114
94199
  }
94115
94200
  logWithTimestamp(
@@ -98130,7 +98215,7 @@ async function getCurrentNodeCliVersion() {
98130
98215
  return await getGlobalNpmPackageVersion(UPDATE_PACKAGES.node) ?? getBundledNodeCliVersion();
98131
98216
  }
98132
98217
  function getBundledNodeCliVersion() {
98133
- return true ? "0.1.6" : null;
98218
+ return true ? "0.1.7" : null;
98134
98219
  }
98135
98220
  function readConfiguredAiProvider() {
98136
98221
  const explicit = process.env.OKX_A2A_AI_PROVIDER || process.env.OKX_AGENT_TASK_AI_CLI;
@@ -98340,7 +98425,7 @@ async function updateHermes(release, options) {
98340
98425
  }
98341
98426
  }
98342
98427
  async function installGatewayPluginForDoctor(target) {
98343
- const release = isPrereleaseVersion("0.1.6") ? "beta" : "latest";
98428
+ const release = isPrereleaseVersion("0.1.7") ? "beta" : "latest";
98344
98429
  const insideTargetGateway = detectGatewayInvocation() === target;
98345
98430
  const options = {
98346
98431
  restart: !insideTargetGateway,
@@ -99138,6 +99223,106 @@ var init_daemon_ops = __esm({
99138
99223
  }
99139
99224
  });
99140
99225
 
99226
+ // src/doctor-sentry.ts
99227
+ var doctor_sentry_exports = {};
99228
+ __export(doctor_sentry_exports, {
99229
+ buildDoctorSentryExtra: () => buildDoctorSentryExtra,
99230
+ reportDoctorCrashToSentry: () => reportDoctorCrashToSentry,
99231
+ reportDoctorRunToSentry: () => reportDoctorRunToSentry
99232
+ });
99233
+ function initDoctorSentry() {
99234
+ if (sentryReady) {
99235
+ return true;
99236
+ }
99237
+ try {
99238
+ const dsn = process.env.OKX_A2A_SENTRY_DSN?.trim() || process.env.SENTRY_DSN?.trim() || FALLBACK_SENTRY_DSN;
99239
+ initLogger({
99240
+ dsn,
99241
+ ...SENTRY_CONFIG,
99242
+ agentPlatform: "node"
99243
+ });
99244
+ sentryReady = true;
99245
+ return true;
99246
+ } catch {
99247
+ return false;
99248
+ }
99249
+ }
99250
+ function buildDoctorSentryExtra(report, meta) {
99251
+ const failedDetails = report.checks.filter((check) => check.status === "fail").map((check) => `${check.id}: ${check.detail}`.slice(0, 160)).join(" | ").slice(0, 900);
99252
+ return {
99253
+ component: "node_direct_cli",
99254
+ source: "direct_cli",
99255
+ operation: "doctor",
99256
+ communicationClass: "node_cli_or_daemon_issue",
99257
+ fixMode: String(meta.fix),
99258
+ nonInteractive: String(meta.nonInteractive),
99259
+ durationMs: String(meta.durationMs),
99260
+ ready: String(report.ready),
99261
+ state: report.state,
99262
+ target: report.target,
99263
+ platform: report.platform,
99264
+ cliVersion: report.cliVersion,
99265
+ blockingFailures: String(report.blockingFailures),
99266
+ checks: report.checks.map((check) => `${check.id}=${check.status}`).join(";"),
99267
+ fixesApplied: report.fixesApplied.map((fixEntry) => `${fixEntry.checkId}=${fixEntry.applied}`).join(";"),
99268
+ ...failedDetails ? { failedDetails } : {},
99269
+ ...report.upgraded ? { upgradedFrom: report.upgraded.from, upgradedTo: report.upgraded.to } : {}
99270
+ };
99271
+ }
99272
+ async function reportDoctorRunToSentry(report, meta) {
99273
+ try {
99274
+ if (!initDoctorSentry()) {
99275
+ return;
99276
+ }
99277
+ const extra = buildDoctorSentryExtra(report, meta);
99278
+ logger.info(LogEvent.DOCTOR_REPORT, extra);
99279
+ if (!report.ready) {
99280
+ const blocking = report.checks.filter((check) => check.status === "fail" && check.severity !== "recommended").map((check) => check.id).join(",");
99281
+ logger.error(
99282
+ LogEvent.DOCTOR_NOT_READY,
99283
+ new Error(`doctor not ready: ${blocking || report.state}`),
99284
+ extra
99285
+ );
99286
+ }
99287
+ await flushBounded();
99288
+ } catch {
99289
+ }
99290
+ }
99291
+ async function reportDoctorCrashToSentry(error, meta) {
99292
+ try {
99293
+ if (!initDoctorSentry()) {
99294
+ return;
99295
+ }
99296
+ logger.error(LogEvent.DOCTOR_CRASHED, error instanceof Error ? error : new Error(String(error)), {
99297
+ component: "node_direct_cli",
99298
+ source: "direct_cli",
99299
+ operation: "doctor",
99300
+ communicationClass: "node_cli_or_daemon_issue",
99301
+ fixMode: String(meta.fix),
99302
+ nonInteractive: String(meta.nonInteractive),
99303
+ durationMs: String(meta.durationMs)
99304
+ });
99305
+ await flushBounded();
99306
+ } catch {
99307
+ }
99308
+ }
99309
+ async function flushBounded() {
99310
+ const timeout = new Promise((resolvePromise) => {
99311
+ const timer = setTimeout(() => resolvePromise(), 1500);
99312
+ timer.unref?.();
99313
+ });
99314
+ await Promise.race([shutdown().then(() => void 0), timeout]);
99315
+ }
99316
+ var sentryReady;
99317
+ var init_doctor_sentry = __esm({
99318
+ "src/doctor-sentry.ts"() {
99319
+ "use strict";
99320
+ init_sentry_config();
99321
+ init_sentry_logger();
99322
+ sentryReady = false;
99323
+ }
99324
+ });
99325
+
99141
99326
  // src/doctor-cli.ts
99142
99327
  var doctor_cli_exports = {};
99143
99328
  __export(doctor_cli_exports, {
@@ -99225,10 +99410,11 @@ async function runDoctor(options = {}) {
99225
99410
  platform: options.platform ?? process.platform,
99226
99411
  env: options.env ?? process.env,
99227
99412
  target: options.target ?? resolveDoctorTarget(options.env ?? process.env),
99228
- cliVersion: options.cliVersion ?? (true ? "0.1.6" : "0.0.0"),
99413
+ cliVersion: options.cliVersion ?? (true ? "0.1.7" : "0.0.0"),
99229
99414
  fixMode: options.fix === true,
99230
99415
  nonInteractive: options.nonInteractive === true,
99231
- packageChanged: false
99416
+ packageChanged: false,
99417
+ hermesGatewayRestartPending: false
99232
99418
  };
99233
99419
  const checkers = options.checkers ?? CHECKERS;
99234
99420
  const fixesApplied = [];
@@ -99390,6 +99576,7 @@ async function handleDoctorCommand(args) {
99390
99576
  setRedirectCommandStdoutToStderr(false);
99391
99577
  }
99392
99578
  };
99579
+ const startedAtMs = Date.now();
99393
99580
  let report;
99394
99581
  try {
99395
99582
  report = await runDoctor({ fix, nonInteractive, ...rawTarget ? { target: rawTarget } : {} });
@@ -99401,10 +99588,14 @@ async function handleDoctorCommand(args) {
99401
99588
  if (!json) {
99402
99589
  console.error(`doctor crashed: ${message}`);
99403
99590
  }
99591
+ const { reportDoctorCrashToSentry: reportDoctorCrashToSentry2 } = await Promise.resolve().then(() => (init_doctor_sentry(), doctor_sentry_exports));
99592
+ await reportDoctorCrashToSentry2(error, { fix, nonInteractive, durationMs: Date.now() - startedAtMs });
99404
99593
  await writeStdoutAndExit(out2, 2);
99405
99594
  return;
99406
99595
  }
99407
99596
  restoreStdout();
99597
+ const { reportDoctorRunToSentry: reportDoctorRunToSentry2 } = await Promise.resolve().then(() => (init_doctor_sentry(), doctor_sentry_exports));
99598
+ await reportDoctorRunToSentry2(report, { fix, nonInteractive, durationMs: Date.now() - startedAtMs });
99408
99599
  const out = json ? `${JSON.stringify(report)}
99409
99600
  ` : `${formatDoctorReportForHumans(report)}
99410
99601
  `;
@@ -99802,6 +99993,20 @@ var init_doctor_cli = __esm({
99802
99993
  const installed = await isGatewayPluginInstalled(ctx.target);
99803
99994
  const hermesPathSuffix = ctx.target === "hermes" ? ` (checked ${resolveHermesPluginYamlPath()})` : "";
99804
99995
  if (installed) {
99996
+ if (ctx.target === "hermes" && ctx.hermesGatewayRestartPending) {
99997
+ return {
99998
+ id: "gateway_plugin",
99999
+ title: "Gateway plugin installed",
100000
+ status: "fail",
100001
+ severity: "required",
100002
+ detail: "the Hermes okx-a2a plugin was just installed/updated in this run, but the running Hermes gateway has not loaded it yet",
100003
+ fix: {
100004
+ kind: "manual",
100005
+ description: "The Hermes okx-a2a plugin was just installed and takes effect after the Hermes gateway restarts \u2014 run /restart inside Hermes (or restart the Hermes app), then re-run okx-a2a doctor to confirm.",
100006
+ command: "/restart"
100007
+ }
100008
+ };
100009
+ }
99805
100010
  return {
99806
100011
  id: "gateway_plugin",
99807
100012
  title: "Gateway plugin installed",
@@ -99833,6 +100038,9 @@ var init_doctor_cli = __esm({
99833
100038
  }
99834
100039
  const { installGatewayPluginForDoctor: installGatewayPluginForDoctor2 } = await Promise.resolve().then(() => (init_update_cli(), update_cli_exports));
99835
100040
  const { gatewayRestarted } = await installGatewayPluginForDoctor2(ctx.target);
100041
+ if (ctx.target === "hermes" && !gatewayRestarted) {
100042
+ ctx.hermesGatewayRestartPending = true;
100043
+ }
99836
100044
  return gatewayRestarted ? `installed the ${ctx.target} okx-a2a plugin and restarted the gateway` : `installed the ${ctx.target} okx-a2a plugin; gateway restart was deferred because doctor is running inside the ${ctx.target} gateway (restarting now would kill this session). Restart the gateway to load the plugin.`;
99837
100045
  }
99838
100046
  };
@@ -100318,7 +100526,7 @@ init_sentry_logger();
100318
100526
  init_sentry_config();
100319
100527
  var CURRENT_GATEWAY_SESSION_KEYS_ENV4 = "OKX_A2A_CURRENT_GATEWAY_SESSION_KEYS";
100320
100528
  function printUsage2() {
100321
- console.log(`okx-a2a ${"0.1.6"}
100529
+ console.log(`okx-a2a ${"0.1.7"}
100322
100530
 
100323
100531
  Usage:
100324
100532
  okx-a2a <command> [options]
@@ -100356,7 +100564,7 @@ Run \`okx-a2a <command> -h\` for command-specific help.
100356
100564
  `);
100357
100565
  }
100358
100566
  function printVersion() {
100359
- console.log("0.1.6");
100567
+ console.log("0.1.7");
100360
100568
  }
100361
100569
  function printDaemonUsage() {
100362
100570
  console.log(`Usage: okx-a2a daemon <start|restart|stop|status|autostart> [options]