@okxweb3/a2a-node 0.2.3 → 0.2.4-beta-e7a52faf6f-260811185020
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.
- package/dist/cli.js +286 -109
- package/dist/index.js +279 -98
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -26604,7 +26604,7 @@ function buildConnectParams(config, instanceId, protocolVersion) {
|
|
|
26604
26604
|
client: {
|
|
26605
26605
|
id: "gateway-client",
|
|
26606
26606
|
displayName: "okx-a2a-node",
|
|
26607
|
-
version: "0.2.
|
|
26607
|
+
version: "0.2.4-beta-e7a52faf6f-260811185020",
|
|
26608
26608
|
platform: "node",
|
|
26609
26609
|
mode: "backend",
|
|
26610
26610
|
instanceId
|
|
@@ -26615,7 +26615,7 @@ function buildConnectParams(config, instanceId, protocolVersion) {
|
|
|
26615
26615
|
commands: [],
|
|
26616
26616
|
permissions: {},
|
|
26617
26617
|
locale: Intl.DateTimeFormat().resolvedOptions().locale || "en-US",
|
|
26618
|
-
userAgent: `okx-a2a-node/${"0.2.
|
|
26618
|
+
userAgent: `okx-a2a-node/${"0.2.4-beta-e7a52faf6f-260811185020"}`,
|
|
26619
26619
|
auth: {
|
|
26620
26620
|
...config.token ? { token: config.token } : {},
|
|
26621
26621
|
...config.password ? { password: config.password } : {}
|
|
@@ -28499,7 +28499,7 @@ var init_sentry_config = __esm({
|
|
|
28499
28499
|
environment = process.env.SENTRY_ENV === "dev" ? "dev" : "prod";
|
|
28500
28500
|
SENTRY_CONFIG = {
|
|
28501
28501
|
projectName: "okx/openclaw-okx-a2a-extension",
|
|
28502
|
-
release: "0.2.
|
|
28502
|
+
release: "0.2.4-beta-e7a52faf6f-260811185020",
|
|
28503
28503
|
environment,
|
|
28504
28504
|
runtimeContainer: normalizeRuntimeContainer(process.env.OKX_A2A_RUNTIME_CONTAINER)
|
|
28505
28505
|
};
|
|
@@ -39669,7 +39669,7 @@ async function exportDiagnosticLogs(options) {
|
|
|
39669
39669
|
node: process.version,
|
|
39670
39670
|
platform: process.platform,
|
|
39671
39671
|
arch: process.arch,
|
|
39672
|
-
packageVersion: true ? "0.2.
|
|
39672
|
+
packageVersion: true ? "0.2.4-beta-e7a52faf6f-260811185020" : "unknown",
|
|
39673
39673
|
sensitiveContentIncluded: options.includeSensitiveContent,
|
|
39674
39674
|
listenerAndLlmContentIncluded: true,
|
|
39675
39675
|
credentialsAlwaysRedacted: true,
|
|
@@ -56122,6 +56122,69 @@ var init_installation_prune = __esm({
|
|
|
56122
56122
|
}
|
|
56123
56123
|
});
|
|
56124
56124
|
|
|
56125
|
+
// ../core/src/xmtp-sdk/onchainos/session-expired.ts
|
|
56126
|
+
function isSessionExpired(stdout) {
|
|
56127
|
+
try {
|
|
56128
|
+
const res = JSON.parse(stdout);
|
|
56129
|
+
return res.ok === false && SESSION_EXPIRED_RE.test(String(res.error ?? ""));
|
|
56130
|
+
} catch {
|
|
56131
|
+
return SESSION_EXPIRED_RE.test(stdout);
|
|
56132
|
+
}
|
|
56133
|
+
}
|
|
56134
|
+
function classifyOnchainosAuthError(err2) {
|
|
56135
|
+
if (!err2) {
|
|
56136
|
+
return null;
|
|
56137
|
+
}
|
|
56138
|
+
const values = [String(err2)];
|
|
56139
|
+
if (typeof err2 === "object") {
|
|
56140
|
+
const anyErr = err2;
|
|
56141
|
+
values.push(anyErr.stdout, anyErr.stderr, anyErr.message);
|
|
56142
|
+
}
|
|
56143
|
+
for (const value of values) {
|
|
56144
|
+
if (typeof value !== "string") {
|
|
56145
|
+
continue;
|
|
56146
|
+
}
|
|
56147
|
+
for (const [reason, pattern] of AUTH_FAILURE_PATTERNS) {
|
|
56148
|
+
if (pattern.test(value)) {
|
|
56149
|
+
return reason;
|
|
56150
|
+
}
|
|
56151
|
+
}
|
|
56152
|
+
}
|
|
56153
|
+
return null;
|
|
56154
|
+
}
|
|
56155
|
+
function isOnchainosAuthError(err2) {
|
|
56156
|
+
return classifyOnchainosAuthError(err2) !== null;
|
|
56157
|
+
}
|
|
56158
|
+
function reportSessionExpired(command) {
|
|
56159
|
+
logger.error(
|
|
56160
|
+
LogEvent.ONCHAINOS_SESSION_EXPIRED,
|
|
56161
|
+
new Error("onchainos session expired"),
|
|
56162
|
+
{
|
|
56163
|
+
component: "onchainos_cli",
|
|
56164
|
+
source: "onchainos",
|
|
56165
|
+
stage: "session_expired",
|
|
56166
|
+
operation: command,
|
|
56167
|
+
command,
|
|
56168
|
+
communicationClass: "onchainos_auth_issue",
|
|
56169
|
+
reason: "session_expired"
|
|
56170
|
+
}
|
|
56171
|
+
);
|
|
56172
|
+
}
|
|
56173
|
+
var SESSION_EXPIRED_RE, AUTH_FAILURE_PATTERNS;
|
|
56174
|
+
var init_session_expired = __esm({
|
|
56175
|
+
"../core/src/xmtp-sdk/onchainos/session-expired.ts"() {
|
|
56176
|
+
"use strict";
|
|
56177
|
+
init_sentry_logger();
|
|
56178
|
+
SESSION_EXPIRED_RE = /session expired/i;
|
|
56179
|
+
AUTH_FAILURE_PATTERNS = [
|
|
56180
|
+
["session_expired", /session expired/i],
|
|
56181
|
+
["not_logged_in", /not logged in/i],
|
|
56182
|
+
["login_required", /login required/i],
|
|
56183
|
+
["authentication_required", /authentication required/i]
|
|
56184
|
+
];
|
|
56185
|
+
}
|
|
56186
|
+
});
|
|
56187
|
+
|
|
56125
56188
|
// ../core/src/xmtp-sdk/index.ts
|
|
56126
56189
|
function cachePath(dataDir, fileName) {
|
|
56127
56190
|
return (0, import_node_path26.join)(dataDir, fileName);
|
|
@@ -56149,21 +56212,6 @@ function stringifyJsonForLog(value) {
|
|
|
56149
56212
|
function ensureCacheDir(dataDir) {
|
|
56150
56213
|
ensureA2aTaskDir(dataDir);
|
|
56151
56214
|
}
|
|
56152
|
-
function isSessionExpiredError(err2) {
|
|
56153
|
-
if (!err2) {
|
|
56154
|
-
return false;
|
|
56155
|
-
}
|
|
56156
|
-
if (typeof err2 === "object") {
|
|
56157
|
-
const anyErr = err2;
|
|
56158
|
-
if (typeof anyErr.stdout === "string" && SESSION_EXPIRED_RE.test(anyErr.stdout)) {
|
|
56159
|
-
return true;
|
|
56160
|
-
}
|
|
56161
|
-
if (typeof anyErr.message === "string" && SESSION_EXPIRED_RE.test(anyErr.message)) {
|
|
56162
|
-
return true;
|
|
56163
|
-
}
|
|
56164
|
-
}
|
|
56165
|
-
return SESSION_EXPIRED_RE.test(String(err2));
|
|
56166
|
-
}
|
|
56167
56215
|
function loadSensitiveWordsFromCache(dataDir) {
|
|
56168
56216
|
try {
|
|
56169
56217
|
const path2 = cachePath(dataDir, "sensitive-words.json");
|
|
@@ -56541,7 +56589,7 @@ function createOfflineReplayAddressSummary(address) {
|
|
|
56541
56589
|
durationMs: 0
|
|
56542
56590
|
};
|
|
56543
56591
|
}
|
|
56544
|
-
var import_node_fs22, import_node_path26, DEFAULT_DATA_DIR, XMTP_INSTALLATION_WARNING_THRESHOLD, XMTP_INSTALLATION_NEAR_LIMIT_THRESHOLD, REPLAY_SCAN_INITIAL_BACKOFF_MS, REPLAY_SCAN_MAX_BACKOFF_MS, SENSITIVE_WORDS_LAZY_RETRY_COOLDOWN_MS,
|
|
56592
|
+
var import_node_fs22, import_node_path26, DEFAULT_DATA_DIR, XMTP_INSTALLATION_WARNING_THRESHOLD, XMTP_INSTALLATION_NEAR_LIMIT_THRESHOLD, REPLAY_SCAN_INITIAL_BACKOFF_MS, REPLAY_SCAN_MAX_BACKOFF_MS, SENSITIVE_WORDS_LAZY_RETRY_COOLDOWN_MS, InboundReplayGate, SYSTEM_CONFIG_DEFAULTS, STREAM_RECOVERY_ALERT_THRESHOLD_MS, REPLAY_GATE_DRAIN_MAX_ATTEMPTS, REPLAY_GATE_DRAIN_RETRY_DELAY_MS, SEMVER_RE, isRecord5, isPositiveNumber, SYSTEM_CONFIG_VALIDATORS, XmtpService;
|
|
56545
56593
|
var init_xmtp_sdk = __esm({
|
|
56546
56594
|
"../core/src/xmtp-sdk/index.ts"() {
|
|
56547
56595
|
"use strict";
|
|
@@ -56559,13 +56607,13 @@ var init_xmtp_sdk = __esm({
|
|
|
56559
56607
|
init_concurrency();
|
|
56560
56608
|
init_a2a_paths();
|
|
56561
56609
|
init_installation_prune();
|
|
56610
|
+
init_session_expired();
|
|
56562
56611
|
DEFAULT_DATA_DIR = resolveA2aTaskPaths().xmtpDir;
|
|
56563
56612
|
XMTP_INSTALLATION_WARNING_THRESHOLD = 2;
|
|
56564
56613
|
XMTP_INSTALLATION_NEAR_LIMIT_THRESHOLD = 8;
|
|
56565
56614
|
REPLAY_SCAN_INITIAL_BACKOFF_MS = 3e4;
|
|
56566
56615
|
REPLAY_SCAN_MAX_BACKOFF_MS = 5 * 6e4;
|
|
56567
56616
|
SENSITIVE_WORDS_LAZY_RETRY_COOLDOWN_MS = 10 * 60 * 1e3;
|
|
56568
|
-
SESSION_EXPIRED_RE = /session expired/i;
|
|
56569
56617
|
InboundReplayGate = class {
|
|
56570
56618
|
constructor(inbound) {
|
|
56571
56619
|
this.inbound = inbound;
|
|
@@ -57131,12 +57179,14 @@ var init_xmtp_sdk = __esm({
|
|
|
57131
57179
|
newAgents = agentList.agents;
|
|
57132
57180
|
changed = agentList.changed;
|
|
57133
57181
|
} catch (err2) {
|
|
57134
|
-
|
|
57182
|
+
const authFailureReason = classifyOnchainosAuthError(err2);
|
|
57183
|
+
if (authFailureReason) {
|
|
57135
57184
|
logWithTimestamp(
|
|
57136
|
-
|
|
57185
|
+
`[xmtp-sdk] refresh: onchainos auth unavailable (${authFailureReason}), taking all local clients offline`
|
|
57137
57186
|
);
|
|
57138
57187
|
logger.info(LogEvent.AGENT_REFRESH_SESSION_EXPIRED, {
|
|
57139
57188
|
onchainosAgentId: "*",
|
|
57189
|
+
authFailureReason,
|
|
57140
57190
|
previousClientCount: String(this.clients.size),
|
|
57141
57191
|
previousAgentCount: String(this.allAgents.length),
|
|
57142
57192
|
previousAgentIds: this.allAgents.map((a) => a.agentId).join(","),
|
|
@@ -58704,39 +58754,6 @@ var init_cli_response = __esm({
|
|
|
58704
58754
|
}
|
|
58705
58755
|
});
|
|
58706
58756
|
|
|
58707
|
-
// ../core/src/xmtp-sdk/onchainos/session-expired.ts
|
|
58708
|
-
function isSessionExpired(stdout) {
|
|
58709
|
-
try {
|
|
58710
|
-
const res = JSON.parse(stdout);
|
|
58711
|
-
return res.ok === false && SESSION_EXPIRED_RE2.test(String(res.error ?? ""));
|
|
58712
|
-
} catch {
|
|
58713
|
-
return SESSION_EXPIRED_RE2.test(stdout);
|
|
58714
|
-
}
|
|
58715
|
-
}
|
|
58716
|
-
function reportSessionExpired(command) {
|
|
58717
|
-
logger.error(
|
|
58718
|
-
LogEvent.ONCHAINOS_SESSION_EXPIRED,
|
|
58719
|
-
new Error("onchainos session expired"),
|
|
58720
|
-
{
|
|
58721
|
-
component: "onchainos_cli",
|
|
58722
|
-
source: "onchainos",
|
|
58723
|
-
stage: "session_expired",
|
|
58724
|
-
operation: command,
|
|
58725
|
-
command,
|
|
58726
|
-
communicationClass: "onchainos_auth_issue",
|
|
58727
|
-
reason: "session_expired"
|
|
58728
|
-
}
|
|
58729
|
-
);
|
|
58730
|
-
}
|
|
58731
|
-
var SESSION_EXPIRED_RE2;
|
|
58732
|
-
var init_session_expired = __esm({
|
|
58733
|
-
"../core/src/xmtp-sdk/onchainos/session-expired.ts"() {
|
|
58734
|
-
"use strict";
|
|
58735
|
-
init_sentry_logger();
|
|
58736
|
-
SESSION_EXPIRED_RE2 = /session expired/i;
|
|
58737
|
-
}
|
|
58738
|
-
});
|
|
58739
|
-
|
|
58740
58757
|
// ../core/src/xmtp-sdk/onchainos/offline-replay-capability.ts
|
|
58741
58758
|
function messageEligibleHelpAdvertisesOfflineReplay(helpText) {
|
|
58742
58759
|
if (typeof helpText !== "string" || helpText.length === 0) {
|
|
@@ -59030,7 +59047,10 @@ async function fetchAgentPage(page) {
|
|
|
59030
59047
|
);
|
|
59031
59048
|
if (!res.ok) {
|
|
59032
59049
|
guardSessionExpired2(stdout, "list-agents");
|
|
59033
|
-
const
|
|
59050
|
+
const detail = typeof res.error === "string" ? res.error.trim() : "";
|
|
59051
|
+
const parseErr = new Error(
|
|
59052
|
+
detail ? `onchainos agent get failed: ${detail}` : "onchainos agent get failed"
|
|
59053
|
+
);
|
|
59034
59054
|
logger.error(
|
|
59035
59055
|
LogEvent.ONCHAINOS_CLI_ERROR,
|
|
59036
59056
|
parseErr,
|
|
@@ -64725,7 +64745,7 @@ async function handleDaemonCommand(command, params) {
|
|
|
64725
64745
|
const payload = await handleXmtpDebugCommand(command, params.service);
|
|
64726
64746
|
return { ok: true, payload };
|
|
64727
64747
|
}
|
|
64728
|
-
const refresh = await params.service.refreshAgents();
|
|
64748
|
+
const refresh = await (params.refreshAgents?.() ?? params.service.refreshAgents());
|
|
64729
64749
|
return {
|
|
64730
64750
|
ok: true,
|
|
64731
64751
|
payload: {
|
|
@@ -67003,9 +67023,13 @@ var init_user_attention_watchers = __esm({
|
|
|
67003
67023
|
// src/listener.ts
|
|
67004
67024
|
var listener_exports = {};
|
|
67005
67025
|
__export(listener_exports, {
|
|
67026
|
+
AgentRefreshAuthGate: () => AgentRefreshAuthGate,
|
|
67027
|
+
AgentRefreshCoordinator: () => AgentRefreshCoordinator,
|
|
67006
67028
|
DEFAULT_OFFLINE_REPLAY_INTERVAL_SEC: () => DEFAULT_OFFLINE_REPLAY_INTERVAL_SEC,
|
|
67007
67029
|
DEFAULT_XMTP_CLIENT_RECYCLE_INTERVAL_SEC: () => DEFAULT_XMTP_CLIENT_RECYCLE_INTERVAL_SEC,
|
|
67008
67030
|
HEARTBEAT_GATEWAY_CHECK_TIMEOUT_MS: () => HEARTBEAT_GATEWAY_CHECK_TIMEOUT_MS,
|
|
67031
|
+
ListenerDeferredTaskScheduler: () => ListenerDeferredTaskScheduler,
|
|
67032
|
+
ListenerMaintenanceGate: () => ListenerMaintenanceGate,
|
|
67009
67033
|
XMTP_CLIENT_RECYCLE_INTERVAL_ENV: () => XMTP_CLIENT_RECYCLE_INTERVAL_ENV,
|
|
67010
67034
|
getHermesGatewayPluginStatus: () => getHermesGatewayPluginStatus,
|
|
67011
67035
|
hermesConfigEnablesOkxA2a: () => hermesConfigEnablesOkxA2a,
|
|
@@ -67013,8 +67037,15 @@ __export(listener_exports, {
|
|
|
67013
67037
|
isHermesGatewayPluginEnabled: () => isHermesGatewayPluginEnabled,
|
|
67014
67038
|
resolveOfflineReplayIntervalSec: () => resolveOfflineReplayIntervalSec,
|
|
67015
67039
|
resolveXmtpClientRecycleIntervalSec: () => resolveXmtpClientRecycleIntervalSec,
|
|
67040
|
+
runHeartbeatRefreshCycle: () => runHeartbeatRefreshCycle,
|
|
67016
67041
|
runListener: () => runListener
|
|
67017
67042
|
});
|
|
67043
|
+
async function runHeartbeatRefreshCycle(options) {
|
|
67044
|
+
const heartbeat = await timeSettled(options.heartbeat);
|
|
67045
|
+
const refreshAllowed = heartbeat.value === "performed" || heartbeat.value === "refresh_safe";
|
|
67046
|
+
const refresh = options.refresh && refreshAllowed ? await timeSettled(options.refresh) : void 0;
|
|
67047
|
+
return { heartbeat, refresh };
|
|
67048
|
+
}
|
|
67018
67049
|
function resolveOfflineReplayIntervalSec(systemConfig) {
|
|
67019
67050
|
const interval = systemConfig.offlineReplayInterval;
|
|
67020
67051
|
if (typeof interval !== "number" || !Number.isFinite(interval) || interval <= 0) {
|
|
@@ -67212,10 +67243,24 @@ async function runListenerWithLock(options, paths) {
|
|
|
67212
67243
|
}
|
|
67213
67244
|
});
|
|
67214
67245
|
logWithTimestamp("[okx-agent-task] user_attention watcher coordinator scanning SQLite watcher state");
|
|
67246
|
+
let stopping = false;
|
|
67215
67247
|
const service = XmtpService.getInstance();
|
|
67248
|
+
const agentRefreshCoordinator = new AgentRefreshCoordinator({
|
|
67249
|
+
lookup: (previousFingerprint) => listAllAgentsWithMetadata(previousFingerprint),
|
|
67250
|
+
refresh: () => service.refreshAgents(),
|
|
67251
|
+
isStopping: () => stopping,
|
|
67252
|
+
onAuthBlocked: () => {
|
|
67253
|
+
logWithTimestamp(
|
|
67254
|
+
"[okx-agent-task] agent refresh auth blocked; periodic agent get paused. After wallet login, run `okx-a2a agent refresh` or restart the daemon"
|
|
67255
|
+
);
|
|
67256
|
+
},
|
|
67257
|
+
onAuthRecovered: () => {
|
|
67258
|
+
logWithTimestamp("[okx-agent-task] agent refresh auth recovered; periodic refresh resumed");
|
|
67259
|
+
}
|
|
67260
|
+
});
|
|
67216
67261
|
service.setDataDir(paths.xmtpDir);
|
|
67217
67262
|
service.setTools({
|
|
67218
|
-
listAllAgentsWithMetadata:
|
|
67263
|
+
listAllAgentsWithMetadata: (previousFingerprint) => agentRefreshCoordinator.lookup(previousFingerprint),
|
|
67219
67264
|
fetchSensitiveWords: async () => fetchSensitiveWords(),
|
|
67220
67265
|
fetchSystemConfig: async () => fetchSystemConfig({
|
|
67221
67266
|
notifySessionExpired: (command) => service.tools.notifySessionExpired?.(command)
|
|
@@ -67242,7 +67287,7 @@ async function runListenerWithLock(options, paths) {
|
|
|
67242
67287
|
}
|
|
67243
67288
|
}),
|
|
67244
67289
|
notifySessionExpired: (command) => {
|
|
67245
|
-
const rawText = `The onchainos login session has expired while running ${command}. Run \`onchainos wallet login\`
|
|
67290
|
+
const rawText = `The onchainos login session has expired while running ${command}. Run \`onchainos wallet login\`, then \`okx-a2a agent refresh\` or restart \`okx-a2a\`.`;
|
|
67246
67291
|
void store.appendBackup(buildSystemStoredMessage({
|
|
67247
67292
|
reason: "onchainos-session-expired",
|
|
67248
67293
|
rawText,
|
|
@@ -67270,12 +67315,12 @@ async function runListenerWithLock(options, paths) {
|
|
|
67270
67315
|
});
|
|
67271
67316
|
}
|
|
67272
67317
|
});
|
|
67273
|
-
service.setPluginVersion("0.2.
|
|
67318
|
+
service.setPluginVersion("0.2.4-beta-e7a52faf6f-260811185020");
|
|
67274
67319
|
await service.init();
|
|
67275
67320
|
const pluginVersionStatus = service.pluginVersionStatus;
|
|
67276
67321
|
if (pluginVersionStatus.unavailable) {
|
|
67277
67322
|
throw new Error(
|
|
67278
|
-
`@okxweb3/a2a-node v${"0.2.
|
|
67323
|
+
`@okxweb3/a2a-node v${"0.2.4-beta-e7a52faf6f-260811185020"} is below the required minimum v${pluginVersionStatus.minVersion}`
|
|
67279
67324
|
);
|
|
67280
67325
|
}
|
|
67281
67326
|
const systemConfig = service.getSystemConfig();
|
|
@@ -67293,7 +67338,7 @@ async function runListenerWithLock(options, paths) {
|
|
|
67293
67338
|
onchainosAgentId: "*",
|
|
67294
67339
|
reason: "system-config missing sentryDsn",
|
|
67295
67340
|
pluginId: "@okxweb3/a2a-node",
|
|
67296
|
-
pluginVersion: "0.2.
|
|
67341
|
+
pluginVersion: "0.2.4-beta-e7a52faf6f-260811185020"
|
|
67297
67342
|
});
|
|
67298
67343
|
}
|
|
67299
67344
|
logWithTimestamp(
|
|
@@ -67305,37 +67350,56 @@ async function runListenerWithLock(options, paths) {
|
|
|
67305
67350
|
logWithTimestamp(
|
|
67306
67351
|
`[okx-agent-task] startup replay complete clients=${startupReplaySummary.clients} replayed=${startupReplaySummary.replayed} skipped=${startupReplaySummary.skipped} duration=${startupReplaySummary.durationMs}ms`
|
|
67307
67352
|
);
|
|
67308
|
-
let maintenanceInFlight = null;
|
|
67309
67353
|
let lastRecycleReplayAtMs = 0;
|
|
67310
|
-
|
|
67311
|
-
const
|
|
67312
|
-
|
|
67313
|
-
|
|
67314
|
-
|
|
67315
|
-
|
|
67316
|
-
return false;
|
|
67354
|
+
const maintenanceGate = new ListenerMaintenanceGate();
|
|
67355
|
+
const deferredMaintenanceTasks = new ListenerDeferredTaskScheduler();
|
|
67356
|
+
const leaveMaintenanceTask = (task) => {
|
|
67357
|
+
const pendingTask = maintenanceGate.leave(task);
|
|
67358
|
+
if (stopping) {
|
|
67359
|
+
return;
|
|
67317
67360
|
}
|
|
67318
|
-
if (
|
|
67319
|
-
|
|
67361
|
+
if (pendingTask === "xmtp_recycle") {
|
|
67362
|
+
deferredMaintenanceTasks.schedule(() => void xmtpRecycleTick());
|
|
67363
|
+
} else if (pendingTask === "offline_replay") {
|
|
67364
|
+
deferredMaintenanceTasks.schedule(() => void offlineReplayTick());
|
|
67320
67365
|
}
|
|
67321
|
-
maintenanceInFlight = task;
|
|
67322
|
-
return true;
|
|
67323
67366
|
};
|
|
67324
|
-
const
|
|
67325
|
-
if (
|
|
67326
|
-
|
|
67327
|
-
|
|
67328
|
-
|
|
67367
|
+
const syncTick = async () => {
|
|
67368
|
+
if (stopping || agentRefreshCoordinator.blocked) {
|
|
67369
|
+
return;
|
|
67370
|
+
}
|
|
67371
|
+
if (!maintenanceGate.tryEnter("sync")) {
|
|
67372
|
+
return;
|
|
67373
|
+
}
|
|
67374
|
+
const tickStartedAt = Date.now();
|
|
67375
|
+
try {
|
|
67376
|
+
const refresh = await agentRefreshCoordinator.runScheduled();
|
|
67377
|
+
if (!refresh) {
|
|
67378
|
+
return;
|
|
67329
67379
|
}
|
|
67380
|
+
logWithTimestamp(
|
|
67381
|
+
`[okx-agent-task] sync tick agents=${refresh.agentCount} changed=${refresh.changed ? "yes" : "no"} added=${refresh.added.length} removed=${refresh.removed.length}`
|
|
67382
|
+
);
|
|
67383
|
+
} catch (err2) {
|
|
67384
|
+
logger.error(LogEvent.DAEMON_TICK_FAILED, err2 instanceof Error ? err2 : new Error(String(err2)), {
|
|
67385
|
+
component: "node_listener",
|
|
67386
|
+
stage: "sync_tick",
|
|
67387
|
+
durationMs: String(Date.now() - tickStartedAt),
|
|
67388
|
+
reason: "sync_tick_exception"
|
|
67389
|
+
});
|
|
67390
|
+
logWithTimestamp(`[okx-agent-task] sync tick failed total=${Date.now() - tickStartedAt}ms:`, err2);
|
|
67391
|
+
} finally {
|
|
67392
|
+
leaveMaintenanceTask("sync");
|
|
67330
67393
|
}
|
|
67331
67394
|
};
|
|
67332
|
-
|
|
67333
|
-
|
|
67334
|
-
|
|
67395
|
+
let heartbeatInFlight = false;
|
|
67396
|
+
const heartbeatTick = async () => {
|
|
67397
|
+
if (heartbeatInFlight || stopping) {
|
|
67398
|
+
return "blocked";
|
|
67335
67399
|
}
|
|
67400
|
+
heartbeatInFlight = true;
|
|
67336
67401
|
const tickStartedAt = Date.now();
|
|
67337
67402
|
try {
|
|
67338
|
-
const refresh = await service.refreshAgents();
|
|
67339
67403
|
const hasActiveAgents = service.getClients().size > 0;
|
|
67340
67404
|
let shouldHeartbeat = hasActiveAgents;
|
|
67341
67405
|
const heartbeatProvider = resolveConfiguredAiProvider({ store: sessionStore }) ?? detectGatewayInvocation();
|
|
@@ -67350,7 +67414,7 @@ async function runListenerWithLock(options, paths) {
|
|
|
67350
67414
|
new Error(`heartbeat gateway check failed: provider=hermes reason=${hermesStatus.reason}`),
|
|
67351
67415
|
{
|
|
67352
67416
|
component: "node_listener",
|
|
67353
|
-
stage: "
|
|
67417
|
+
stage: "heartbeat_tick",
|
|
67354
67418
|
reason: hermesStatus.reason ?? "unknown",
|
|
67355
67419
|
provider: "hermes",
|
|
67356
67420
|
hermesHome: hermesStatus.hermesHome,
|
|
@@ -67374,7 +67438,7 @@ async function runListenerWithLock(options, paths) {
|
|
|
67374
67438
|
new Error(`heartbeat skipped: provider=${heartbeatProvider ?? "(not set)"} gateway unavailable`),
|
|
67375
67439
|
{
|
|
67376
67440
|
component: "node_listener",
|
|
67377
|
-
stage: "
|
|
67441
|
+
stage: "heartbeat_tick",
|
|
67378
67442
|
reason: "gateway_unavailable",
|
|
67379
67443
|
provider: heartbeatProvider ?? "(not set)",
|
|
67380
67444
|
chainIndex: ONCHAINOS_CHAIN_INDEX,
|
|
@@ -67390,7 +67454,7 @@ async function runListenerWithLock(options, paths) {
|
|
|
67390
67454
|
new Error("heartbeat skipped: no active agents"),
|
|
67391
67455
|
{
|
|
67392
67456
|
component: "node_listener",
|
|
67393
|
-
stage: "
|
|
67457
|
+
stage: "heartbeat_tick",
|
|
67394
67458
|
reason: "no_active_agents",
|
|
67395
67459
|
provider: heartbeatProvider ?? "(not set)",
|
|
67396
67460
|
chainIndex: ONCHAINOS_CHAIN_INDEX
|
|
@@ -67403,7 +67467,7 @@ async function runListenerWithLock(options, paths) {
|
|
|
67403
67467
|
if (shouldHeartbeat && heartbeatResult.error) {
|
|
67404
67468
|
logger.error(LogEvent.HEARTBEAT_FAILED, heartbeatResult.error instanceof Error ? heartbeatResult.error : new Error(String(heartbeatResult.error)), {
|
|
67405
67469
|
component: "node_listener",
|
|
67406
|
-
stage: "
|
|
67470
|
+
stage: "heartbeat_tick",
|
|
67407
67471
|
reason: heartbeatResult.error instanceof Error ? heartbeatResult.error.name : "unknown_error",
|
|
67408
67472
|
durationMs: String(heartbeatMs),
|
|
67409
67473
|
chainIndex: ONCHAINOS_CHAIN_INDEX,
|
|
@@ -67411,23 +67475,27 @@ async function runListenerWithLock(options, paths) {
|
|
|
67411
67475
|
});
|
|
67412
67476
|
logWithTimestamp(`[okx-agent-task] heartbeat failed duration=${heartbeatMs}ms:`, heartbeatResult.error);
|
|
67413
67477
|
}
|
|
67414
|
-
|
|
67415
|
-
`[okx-agent-task] sync tick agents=${refresh.agentCount} changed=${refresh.changed ? "yes" : "no"} added=${refresh.added.length} removed=${refresh.removed.length}`
|
|
67416
|
-
);
|
|
67478
|
+
return shouldHeartbeat ? "performed" : "refresh_safe";
|
|
67417
67479
|
} catch (err2) {
|
|
67418
|
-
logger.error(LogEvent.
|
|
67480
|
+
logger.error(LogEvent.HEARTBEAT_FAILED, err2 instanceof Error ? err2 : new Error(String(err2)), {
|
|
67419
67481
|
component: "node_listener",
|
|
67420
|
-
stage: "
|
|
67482
|
+
stage: "heartbeat_tick",
|
|
67421
67483
|
durationMs: String(Date.now() - tickStartedAt),
|
|
67422
|
-
reason: "
|
|
67484
|
+
reason: "heartbeat_tick_exception",
|
|
67485
|
+
chainIndex: ONCHAINOS_CHAIN_INDEX,
|
|
67486
|
+
communicationClass: "onchainos_or_network"
|
|
67423
67487
|
});
|
|
67424
|
-
logWithTimestamp(`[okx-agent-task]
|
|
67488
|
+
logWithTimestamp(`[okx-agent-task] heartbeat tick failed total=${Date.now() - tickStartedAt}ms:`, err2);
|
|
67489
|
+
return "blocked";
|
|
67425
67490
|
} finally {
|
|
67426
|
-
|
|
67491
|
+
heartbeatInFlight = false;
|
|
67427
67492
|
}
|
|
67428
67493
|
};
|
|
67429
67494
|
const offlineReplayTick = async () => {
|
|
67430
|
-
if (
|
|
67495
|
+
if (stopping) {
|
|
67496
|
+
return;
|
|
67497
|
+
}
|
|
67498
|
+
if (!maintenanceGate.tryEnter("offline_replay")) {
|
|
67431
67499
|
return;
|
|
67432
67500
|
}
|
|
67433
67501
|
const tickStartedAt = Date.now();
|
|
@@ -67469,8 +67537,10 @@ async function runListenerWithLock(options, paths) {
|
|
|
67469
67537
|
}
|
|
67470
67538
|
};
|
|
67471
67539
|
const xmtpRecycleTick = async () => {
|
|
67472
|
-
if (
|
|
67473
|
-
|
|
67540
|
+
if (stopping) {
|
|
67541
|
+
return;
|
|
67542
|
+
}
|
|
67543
|
+
if (!maintenanceGate.tryEnter("xmtp_recycle")) {
|
|
67474
67544
|
return;
|
|
67475
67545
|
}
|
|
67476
67546
|
const tickStartedAt = Date.now();
|
|
@@ -67514,7 +67584,6 @@ async function runListenerWithLock(options, paths) {
|
|
|
67514
67584
|
let timer;
|
|
67515
67585
|
let offlineReplayTimer;
|
|
67516
67586
|
let xmtpClientRecycleTimer;
|
|
67517
|
-
let stopping = false;
|
|
67518
67587
|
const scheduleSyncTimer = (nextIntervalSec) => {
|
|
67519
67588
|
if (stopping) {
|
|
67520
67589
|
return;
|
|
@@ -67525,7 +67594,10 @@ async function runListenerWithLock(options, paths) {
|
|
|
67525
67594
|
intervalSec = Math.max(10, nextIntervalSec);
|
|
67526
67595
|
logWithTimestamp(`[okx-agent-task] scheduled sync interval ${intervalSec}s`);
|
|
67527
67596
|
timer = setInterval(() => {
|
|
67528
|
-
void
|
|
67597
|
+
void runHeartbeatRefreshCycle({
|
|
67598
|
+
heartbeat: heartbeatTick,
|
|
67599
|
+
refresh: syncTick
|
|
67600
|
+
});
|
|
67529
67601
|
}, intervalSec * 1e3);
|
|
67530
67602
|
};
|
|
67531
67603
|
const scheduleOfflineReplayTimer = (nextIntervalSec) => {
|
|
@@ -67607,9 +67679,12 @@ async function runListenerWithLock(options, paths) {
|
|
|
67607
67679
|
const systemConfigRefreshTimer = setInterval(() => {
|
|
67608
67680
|
void refreshSystemConfigTick();
|
|
67609
67681
|
}, 60 * 60 * 1e3);
|
|
67610
|
-
void
|
|
67682
|
+
void runHeartbeatRefreshCycle({
|
|
67683
|
+
heartbeat: heartbeatTick
|
|
67684
|
+
});
|
|
67611
67685
|
const commandProcessor = startCommandProcessor({
|
|
67612
67686
|
service,
|
|
67687
|
+
refreshAgents: () => agentRefreshCoordinator.runManual(),
|
|
67613
67688
|
store,
|
|
67614
67689
|
sessionStore,
|
|
67615
67690
|
homeDir: options.homeDir
|
|
@@ -67628,6 +67703,7 @@ async function runListenerWithLock(options, paths) {
|
|
|
67628
67703
|
resolve14();
|
|
67629
67704
|
}, SHUTDOWN_FORCE_RESOLVE_MS);
|
|
67630
67705
|
void (async () => {
|
|
67706
|
+
deferredMaintenanceTasks.cancelAll();
|
|
67631
67707
|
if (timer) {
|
|
67632
67708
|
clearInterval(timer);
|
|
67633
67709
|
}
|
|
@@ -67669,7 +67745,7 @@ async function timeSettled(fn) {
|
|
|
67669
67745
|
return { durationMs: Date.now() - startedAt, error };
|
|
67670
67746
|
}
|
|
67671
67747
|
}
|
|
67672
|
-
var import_node_fs25, import_promises13, import_node_os11, import_node_path30, DEFAULT_OFFLINE_REPLAY_INTERVAL_SEC, DEFAULT_XMTP_CLIENT_RECYCLE_INTERVAL_SEC, XMTP_CLIENT_RECYCLE_INTERVAL_ENV, HEARTBEAT_GATEWAY_CHECK_TIMEOUT_MS, UPGRADE_RECOMMENDATION_IDEMPOTENCY_KEY, SHUTDOWN_FORCE_RESOLVE_MS;
|
|
67748
|
+
var import_node_fs25, import_promises13, import_node_os11, import_node_path30, DEFAULT_OFFLINE_REPLAY_INTERVAL_SEC, DEFAULT_XMTP_CLIENT_RECYCLE_INTERVAL_SEC, XMTP_CLIENT_RECYCLE_INTERVAL_ENV, HEARTBEAT_GATEWAY_CHECK_TIMEOUT_MS, AgentRefreshAuthGate, AgentRefreshCoordinator, ListenerDeferredTaskScheduler, ListenerMaintenanceGate, UPGRADE_RECOMMENDATION_IDEMPOTENCY_KEY, SHUTDOWN_FORCE_RESOLVE_MS;
|
|
67673
67749
|
var init_listener = __esm({
|
|
67674
67750
|
"src/listener.ts"() {
|
|
67675
67751
|
"use strict";
|
|
@@ -67702,6 +67778,107 @@ var init_listener = __esm({
|
|
|
67702
67778
|
DEFAULT_XMTP_CLIENT_RECYCLE_INTERVAL_SEC = 6 * 60 * 60;
|
|
67703
67779
|
XMTP_CLIENT_RECYCLE_INTERVAL_ENV = "OKX_A2A_XMTP_CLIENT_RECYCLE_INTERVAL_SEC";
|
|
67704
67780
|
HEARTBEAT_GATEWAY_CHECK_TIMEOUT_MS = 2e3;
|
|
67781
|
+
AgentRefreshAuthGate = class {
|
|
67782
|
+
authBlocked = false;
|
|
67783
|
+
get blocked() {
|
|
67784
|
+
return this.authBlocked;
|
|
67785
|
+
}
|
|
67786
|
+
recordSuccess() {
|
|
67787
|
+
this.authBlocked = false;
|
|
67788
|
+
}
|
|
67789
|
+
recordFailure(err2) {
|
|
67790
|
+
if (!isOnchainosAuthError(err2)) {
|
|
67791
|
+
return false;
|
|
67792
|
+
}
|
|
67793
|
+
this.authBlocked = true;
|
|
67794
|
+
return true;
|
|
67795
|
+
}
|
|
67796
|
+
};
|
|
67797
|
+
AgentRefreshCoordinator = class {
|
|
67798
|
+
constructor(options) {
|
|
67799
|
+
this.options = options;
|
|
67800
|
+
}
|
|
67801
|
+
options;
|
|
67802
|
+
authGate = new AgentRefreshAuthGate();
|
|
67803
|
+
get blocked() {
|
|
67804
|
+
return this.authGate.blocked;
|
|
67805
|
+
}
|
|
67806
|
+
async lookup(previousFingerprint) {
|
|
67807
|
+
const wasBlocked = this.authGate.blocked;
|
|
67808
|
+
try {
|
|
67809
|
+
const result = await this.options.lookup(previousFingerprint);
|
|
67810
|
+
this.authGate.recordSuccess();
|
|
67811
|
+
if (wasBlocked) {
|
|
67812
|
+
this.options.onAuthRecovered?.();
|
|
67813
|
+
}
|
|
67814
|
+
return result;
|
|
67815
|
+
} catch (err2) {
|
|
67816
|
+
if (this.authGate.recordFailure(err2) && !wasBlocked) {
|
|
67817
|
+
this.options.onAuthBlocked?.();
|
|
67818
|
+
}
|
|
67819
|
+
throw err2;
|
|
67820
|
+
}
|
|
67821
|
+
}
|
|
67822
|
+
async runScheduled() {
|
|
67823
|
+
if (this.options.isStopping() || this.authGate.blocked) {
|
|
67824
|
+
return null;
|
|
67825
|
+
}
|
|
67826
|
+
return this.options.refresh();
|
|
67827
|
+
}
|
|
67828
|
+
async runManual() {
|
|
67829
|
+
return this.options.refresh();
|
|
67830
|
+
}
|
|
67831
|
+
};
|
|
67832
|
+
ListenerDeferredTaskScheduler = class {
|
|
67833
|
+
timers = /* @__PURE__ */ new Set();
|
|
67834
|
+
schedule(task) {
|
|
67835
|
+
const timer = setTimeout(() => {
|
|
67836
|
+
this.timers.delete(timer);
|
|
67837
|
+
task();
|
|
67838
|
+
}, 0);
|
|
67839
|
+
this.timers.add(timer);
|
|
67840
|
+
}
|
|
67841
|
+
cancelAll() {
|
|
67842
|
+
for (const timer of this.timers) {
|
|
67843
|
+
clearTimeout(timer);
|
|
67844
|
+
}
|
|
67845
|
+
this.timers.clear();
|
|
67846
|
+
}
|
|
67847
|
+
};
|
|
67848
|
+
ListenerMaintenanceGate = class {
|
|
67849
|
+
inFlight = null;
|
|
67850
|
+
offlineReplayPending = false;
|
|
67851
|
+
xmtpRecyclePending = false;
|
|
67852
|
+
tryEnter(task) {
|
|
67853
|
+
if (task !== "xmtp_recycle" && this.xmtpRecyclePending || this.inFlight) {
|
|
67854
|
+
if (task === "offline_replay") {
|
|
67855
|
+
this.offlineReplayPending = true;
|
|
67856
|
+
} else if (task === "xmtp_recycle") {
|
|
67857
|
+
this.xmtpRecyclePending = true;
|
|
67858
|
+
}
|
|
67859
|
+
return false;
|
|
67860
|
+
}
|
|
67861
|
+
if (task === "xmtp_recycle") {
|
|
67862
|
+
this.xmtpRecyclePending = false;
|
|
67863
|
+
}
|
|
67864
|
+
this.inFlight = task;
|
|
67865
|
+
return true;
|
|
67866
|
+
}
|
|
67867
|
+
leave(task) {
|
|
67868
|
+
if (this.inFlight !== task) {
|
|
67869
|
+
return null;
|
|
67870
|
+
}
|
|
67871
|
+
this.inFlight = null;
|
|
67872
|
+
if (this.xmtpRecyclePending) {
|
|
67873
|
+
return "xmtp_recycle";
|
|
67874
|
+
}
|
|
67875
|
+
if (this.offlineReplayPending) {
|
|
67876
|
+
this.offlineReplayPending = false;
|
|
67877
|
+
return "offline_replay";
|
|
67878
|
+
}
|
|
67879
|
+
return null;
|
|
67880
|
+
}
|
|
67881
|
+
};
|
|
67705
67882
|
UPGRADE_RECOMMENDATION_IDEMPOTENCY_KEY = "system:onchainos-offline-replay-upgrade";
|
|
67706
67883
|
SHUTDOWN_FORCE_RESOLVE_MS = 5e3;
|
|
67707
67884
|
}
|
|
@@ -115480,7 +115657,7 @@ async function getCurrentNodeCliVersion() {
|
|
|
115480
115657
|
return await getGlobalNpmPackageVersion(UPDATE_PACKAGES.node) ?? getBundledNodeCliVersion();
|
|
115481
115658
|
}
|
|
115482
115659
|
function getBundledNodeCliVersion() {
|
|
115483
|
-
return true ? "0.2.
|
|
115660
|
+
return true ? "0.2.4-beta-e7a52faf6f-260811185020" : null;
|
|
115484
115661
|
}
|
|
115485
115662
|
function readConfiguredAiProvider() {
|
|
115486
115663
|
const explicit = process.env.OKX_A2A_AI_PROVIDER || process.env.OKX_AGENT_TASK_AI_CLI;
|
|
@@ -115690,7 +115867,7 @@ async function updateHermes(release, options) {
|
|
|
115690
115867
|
}
|
|
115691
115868
|
}
|
|
115692
115869
|
async function installGatewayPluginForDoctor(target) {
|
|
115693
|
-
const release = isPrereleaseVersion("0.2.
|
|
115870
|
+
const release = isPrereleaseVersion("0.2.4-beta-e7a52faf6f-260811185020") ? "beta" : "latest";
|
|
115694
115871
|
const insideTargetGateway = detectGatewayInvocation() === target;
|
|
115695
115872
|
const options = {
|
|
115696
115873
|
restart: !insideTargetGateway,
|
|
@@ -116733,7 +116910,7 @@ async function runDoctor(options = {}) {
|
|
|
116733
116910
|
platform: options.platform ?? process.platform,
|
|
116734
116911
|
env: options.env ?? process.env,
|
|
116735
116912
|
target: options.target ?? resolveDoctorTarget(options.env ?? process.env),
|
|
116736
|
-
cliVersion: options.cliVersion ?? (true ? "0.2.
|
|
116913
|
+
cliVersion: options.cliVersion ?? (true ? "0.2.4-beta-e7a52faf6f-260811185020" : "0.0.0"),
|
|
116737
116914
|
fixMode: options.fix === true,
|
|
116738
116915
|
nonInteractive: options.nonInteractive === true,
|
|
116739
116916
|
packageChanged: false,
|
|
@@ -117730,7 +117907,7 @@ init_sentry_logger();
|
|
|
117730
117907
|
init_sentry_config();
|
|
117731
117908
|
var CURRENT_GATEWAY_SESSION_KEYS_ENV4 = "OKX_A2A_CURRENT_GATEWAY_SESSION_KEYS";
|
|
117732
117909
|
function printUsage3() {
|
|
117733
|
-
console.log(`okx-a2a ${"0.2.
|
|
117910
|
+
console.log(`okx-a2a ${"0.2.4-beta-e7a52faf6f-260811185020"}
|
|
117734
117911
|
|
|
117735
117912
|
Usage:
|
|
117736
117913
|
okx-a2a <command> [options]
|
|
@@ -117770,7 +117947,7 @@ Run \`okx-a2a <command> -h\` for command-specific help.
|
|
|
117770
117947
|
`);
|
|
117771
117948
|
}
|
|
117772
117949
|
function printVersion() {
|
|
117773
|
-
console.log("0.2.
|
|
117950
|
+
console.log("0.2.4-beta-e7a52faf6f-260811185020");
|
|
117774
117951
|
}
|
|
117775
117952
|
function printDaemonUsage() {
|
|
117776
117953
|
console.log(`Usage: okx-a2a daemon <start|restart|stop|status|autostart> [options]
|
|
@@ -119206,7 +119383,7 @@ async function main() {
|
|
|
119206
119383
|
if (command === "xmtp-test") {
|
|
119207
119384
|
const { handleXmtpTestCommand: handleXmtpTestCommand2 } = await Promise.resolve().then(() => (init_xmtp_test_cli(), xmtp_test_cli_exports));
|
|
119208
119385
|
await handleXmtpTestCommand2(process.argv.slice(3), {
|
|
119209
|
-
packageVersion: "0.2.
|
|
119386
|
+
packageVersion: "0.2.4-beta-e7a52faf6f-260811185020",
|
|
119210
119387
|
agentSdkVersion: "2.3.0",
|
|
119211
119388
|
nodeSdkVersion: "6.1.0",
|
|
119212
119389
|
nodeBindingsVersion: "1.11.0"
|
package/dist/index.js
CHANGED
|
@@ -32104,7 +32104,7 @@ var init_sentry_config = __esm({
|
|
|
32104
32104
|
environment = process.env.SENTRY_ENV === "dev" ? "dev" : "prod";
|
|
32105
32105
|
SENTRY_CONFIG = {
|
|
32106
32106
|
projectName: "okx/openclaw-okx-a2a-extension",
|
|
32107
|
-
release: "0.2.
|
|
32107
|
+
release: "0.2.4-beta-e7a52faf6f-260811185020",
|
|
32108
32108
|
environment,
|
|
32109
32109
|
runtimeContainer: normalizeRuntimeContainer(process.env.OKX_A2A_RUNTIME_CONTAINER)
|
|
32110
32110
|
};
|
|
@@ -33045,7 +33045,7 @@ async function getCurrentNodeCliVersion() {
|
|
|
33045
33045
|
return await getGlobalNpmPackageVersion(UPDATE_PACKAGES.node) ?? getBundledNodeCliVersion();
|
|
33046
33046
|
}
|
|
33047
33047
|
function getBundledNodeCliVersion() {
|
|
33048
|
-
return true ? "0.2.
|
|
33048
|
+
return true ? "0.2.4-beta-e7a52faf6f-260811185020" : null;
|
|
33049
33049
|
}
|
|
33050
33050
|
function readConfiguredAiProvider() {
|
|
33051
33051
|
const explicit = process.env.OKX_A2A_AI_PROVIDER || process.env.OKX_AGENT_TASK_AI_CLI;
|
|
@@ -33255,7 +33255,7 @@ async function updateHermes(release, options) {
|
|
|
33255
33255
|
}
|
|
33256
33256
|
}
|
|
33257
33257
|
async function installGatewayPluginForDoctor(target) {
|
|
33258
|
-
const release = isPrereleaseVersion("0.2.
|
|
33258
|
+
const release = isPrereleaseVersion("0.2.4-beta-e7a52faf6f-260811185020") ? "beta" : "latest";
|
|
33259
33259
|
const insideTargetGateway = detectGatewayInvocation() === target;
|
|
33260
33260
|
const options = {
|
|
33261
33261
|
restart: !insideTargetGateway,
|
|
@@ -43946,6 +43946,8 @@ var index_exports = {};
|
|
|
43946
43946
|
__export(index_exports, {
|
|
43947
43947
|
AI_PROVIDERS: () => AI_PROVIDERS,
|
|
43948
43948
|
AgentMessageDirection: () => AgentMessageDirection,
|
|
43949
|
+
AgentRefreshAuthGate: () => AgentRefreshAuthGate,
|
|
43950
|
+
AgentRefreshCoordinator: () => AgentRefreshCoordinator,
|
|
43949
43951
|
AiRunner: () => AiRunner,
|
|
43950
43952
|
BACKUP_JOB_ID: () => BACKUP_JOB_ID,
|
|
43951
43953
|
CODEX_APP_DIRS_ENV: () => CODEX_APP_DIRS_ENV,
|
|
@@ -43965,6 +43967,8 @@ __export(index_exports, {
|
|
|
43965
43967
|
InboundReplayGate: () => InboundReplayGate,
|
|
43966
43968
|
InvalidXmtpMessageStore: () => InvalidXmtpMessageStore,
|
|
43967
43969
|
JOB_PROVIDER_BINDING_SOURCES: () => JOB_PROVIDER_BINDING_SOURCES,
|
|
43970
|
+
ListenerDeferredTaskScheduler: () => ListenerDeferredTaskScheduler,
|
|
43971
|
+
ListenerMaintenanceGate: () => ListenerMaintenanceGate,
|
|
43968
43972
|
LogEvent: () => LogEvent,
|
|
43969
43973
|
MESSAGE_ELIGIBLE_OFFLINE_REPLAY_FLAG: () => MESSAGE_ELIGIBLE_OFFLINE_REPLAY_FLAG,
|
|
43970
43974
|
MESSAGE_ELIGIBLE_OFFLINE_REPLAY_HELP_TOKEN: () => MESSAGE_ELIGIBLE_OFFLINE_REPLAY_HELP_TOKEN,
|
|
@@ -44161,6 +44165,7 @@ __export(index_exports, {
|
|
|
44161
44165
|
resolveXmtpClientRecycleIntervalSec: () => resolveXmtpClientRecycleIntervalSec,
|
|
44162
44166
|
runAiAdapter: () => runAiAdapter,
|
|
44163
44167
|
runDoctor: () => runDoctor,
|
|
44168
|
+
runHeartbeatRefreshCycle: () => runHeartbeatRefreshCycle,
|
|
44164
44169
|
runListener: () => runListener,
|
|
44165
44170
|
scanUserAttentionWatchers: () => scanUserAttentionWatchers,
|
|
44166
44171
|
setOpenClawWebSocketFactoryForTests: () => setOpenClawWebSocketFactoryForTests,
|
|
@@ -55865,6 +55870,63 @@ function compareTimestamp(a, b) {
|
|
|
55865
55870
|
return 0;
|
|
55866
55871
|
}
|
|
55867
55872
|
|
|
55873
|
+
// ../core/src/xmtp-sdk/onchainos/session-expired.ts
|
|
55874
|
+
init_sentry_logger();
|
|
55875
|
+
var SESSION_EXPIRED_RE = /session expired/i;
|
|
55876
|
+
var AUTH_FAILURE_PATTERNS = [
|
|
55877
|
+
["session_expired", /session expired/i],
|
|
55878
|
+
["not_logged_in", /not logged in/i],
|
|
55879
|
+
["login_required", /login required/i],
|
|
55880
|
+
["authentication_required", /authentication required/i]
|
|
55881
|
+
];
|
|
55882
|
+
function isSessionExpired(stdout) {
|
|
55883
|
+
try {
|
|
55884
|
+
const res = JSON.parse(stdout);
|
|
55885
|
+
return res.ok === false && SESSION_EXPIRED_RE.test(String(res.error ?? ""));
|
|
55886
|
+
} catch {
|
|
55887
|
+
return SESSION_EXPIRED_RE.test(stdout);
|
|
55888
|
+
}
|
|
55889
|
+
}
|
|
55890
|
+
function classifyOnchainosAuthError(err) {
|
|
55891
|
+
if (!err) {
|
|
55892
|
+
return null;
|
|
55893
|
+
}
|
|
55894
|
+
const values = [String(err)];
|
|
55895
|
+
if (typeof err === "object") {
|
|
55896
|
+
const anyErr = err;
|
|
55897
|
+
values.push(anyErr.stdout, anyErr.stderr, anyErr.message);
|
|
55898
|
+
}
|
|
55899
|
+
for (const value of values) {
|
|
55900
|
+
if (typeof value !== "string") {
|
|
55901
|
+
continue;
|
|
55902
|
+
}
|
|
55903
|
+
for (const [reason, pattern] of AUTH_FAILURE_PATTERNS) {
|
|
55904
|
+
if (pattern.test(value)) {
|
|
55905
|
+
return reason;
|
|
55906
|
+
}
|
|
55907
|
+
}
|
|
55908
|
+
}
|
|
55909
|
+
return null;
|
|
55910
|
+
}
|
|
55911
|
+
function isOnchainosAuthError(err) {
|
|
55912
|
+
return classifyOnchainosAuthError(err) !== null;
|
|
55913
|
+
}
|
|
55914
|
+
function reportSessionExpired(command) {
|
|
55915
|
+
logger.error(
|
|
55916
|
+
LogEvent.ONCHAINOS_SESSION_EXPIRED,
|
|
55917
|
+
new Error("onchainos session expired"),
|
|
55918
|
+
{
|
|
55919
|
+
component: "onchainos_cli",
|
|
55920
|
+
source: "onchainos",
|
|
55921
|
+
stage: "session_expired",
|
|
55922
|
+
operation: command,
|
|
55923
|
+
command,
|
|
55924
|
+
communicationClass: "onchainos_auth_issue",
|
|
55925
|
+
reason: "session_expired"
|
|
55926
|
+
}
|
|
55927
|
+
);
|
|
55928
|
+
}
|
|
55929
|
+
|
|
55868
55930
|
// ../core/src/xmtp-sdk/index.ts
|
|
55869
55931
|
var DEFAULT_DATA_DIR = resolveA2aTaskPaths().xmtpDir;
|
|
55870
55932
|
var XMTP_INSTALLATION_WARNING_THRESHOLD = 2;
|
|
@@ -55898,22 +55960,6 @@ function ensureCacheDir(dataDir) {
|
|
|
55898
55960
|
ensureA2aTaskDir(dataDir);
|
|
55899
55961
|
}
|
|
55900
55962
|
var SENSITIVE_WORDS_LAZY_RETRY_COOLDOWN_MS = 10 * 60 * 1e3;
|
|
55901
|
-
var SESSION_EXPIRED_RE = /session expired/i;
|
|
55902
|
-
function isSessionExpiredError(err) {
|
|
55903
|
-
if (!err) {
|
|
55904
|
-
return false;
|
|
55905
|
-
}
|
|
55906
|
-
if (typeof err === "object") {
|
|
55907
|
-
const anyErr = err;
|
|
55908
|
-
if (typeof anyErr.stdout === "string" && SESSION_EXPIRED_RE.test(anyErr.stdout)) {
|
|
55909
|
-
return true;
|
|
55910
|
-
}
|
|
55911
|
-
if (typeof anyErr.message === "string" && SESSION_EXPIRED_RE.test(anyErr.message)) {
|
|
55912
|
-
return true;
|
|
55913
|
-
}
|
|
55914
|
-
}
|
|
55915
|
-
return SESSION_EXPIRED_RE.test(String(err));
|
|
55916
|
-
}
|
|
55917
55963
|
function loadSensitiveWordsFromCache(dataDir) {
|
|
55918
55964
|
try {
|
|
55919
55965
|
const path2 = cachePath(dataDir, "sensitive-words.json");
|
|
@@ -56832,12 +56878,14 @@ var XmtpService = class _XmtpService {
|
|
|
56832
56878
|
newAgents = agentList.agents;
|
|
56833
56879
|
changed = agentList.changed;
|
|
56834
56880
|
} catch (err) {
|
|
56835
|
-
|
|
56881
|
+
const authFailureReason = classifyOnchainosAuthError(err);
|
|
56882
|
+
if (authFailureReason) {
|
|
56836
56883
|
logWithTimestamp(
|
|
56837
|
-
|
|
56884
|
+
`[xmtp-sdk] refresh: onchainos auth unavailable (${authFailureReason}), taking all local clients offline`
|
|
56838
56885
|
);
|
|
56839
56886
|
logger.info(LogEvent.AGENT_REFRESH_SESSION_EXPIRED, {
|
|
56840
56887
|
onchainosAgentId: "*",
|
|
56888
|
+
authFailureReason,
|
|
56841
56889
|
previousClientCount: String(this.clients.size),
|
|
56842
56890
|
previousAgentCount: String(this.allAgents.length),
|
|
56843
56891
|
previousAgentIds: this.allAgents.map((a) => a.agentId).join(","),
|
|
@@ -58744,33 +58792,6 @@ function parseCliJson(stdout, command, extras = {}) {
|
|
|
58744
58792
|
}
|
|
58745
58793
|
}
|
|
58746
58794
|
|
|
58747
|
-
// ../core/src/xmtp-sdk/onchainos/session-expired.ts
|
|
58748
|
-
init_sentry_logger();
|
|
58749
|
-
var SESSION_EXPIRED_RE2 = /session expired/i;
|
|
58750
|
-
function isSessionExpired(stdout) {
|
|
58751
|
-
try {
|
|
58752
|
-
const res = JSON.parse(stdout);
|
|
58753
|
-
return res.ok === false && SESSION_EXPIRED_RE2.test(String(res.error ?? ""));
|
|
58754
|
-
} catch {
|
|
58755
|
-
return SESSION_EXPIRED_RE2.test(stdout);
|
|
58756
|
-
}
|
|
58757
|
-
}
|
|
58758
|
-
function reportSessionExpired(command) {
|
|
58759
|
-
logger.error(
|
|
58760
|
-
LogEvent.ONCHAINOS_SESSION_EXPIRED,
|
|
58761
|
-
new Error("onchainos session expired"),
|
|
58762
|
-
{
|
|
58763
|
-
component: "onchainos_cli",
|
|
58764
|
-
source: "onchainos",
|
|
58765
|
-
stage: "session_expired",
|
|
58766
|
-
operation: command,
|
|
58767
|
-
command,
|
|
58768
|
-
communicationClass: "onchainos_auth_issue",
|
|
58769
|
-
reason: "session_expired"
|
|
58770
|
-
}
|
|
58771
|
-
);
|
|
58772
|
-
}
|
|
58773
|
-
|
|
58774
58795
|
// ../core/src/xmtp-sdk/onchainos/offline-replay-capability.ts
|
|
58775
58796
|
init_log();
|
|
58776
58797
|
var MESSAGE_ELIGIBLE_OFFLINE_REPLAY_FLAG = "--is-offline-replay";
|
|
@@ -59056,7 +59077,10 @@ async function fetchAgentPage(page) {
|
|
|
59056
59077
|
);
|
|
59057
59078
|
if (!res.ok) {
|
|
59058
59079
|
guardSessionExpired2(stdout, "list-agents");
|
|
59059
|
-
const
|
|
59080
|
+
const detail = typeof res.error === "string" ? res.error.trim() : "";
|
|
59081
|
+
const parseErr = new Error(
|
|
59082
|
+
detail ? `onchainos agent get failed: ${detail}` : "onchainos agent get failed"
|
|
59083
|
+
);
|
|
59060
59084
|
logger.error(
|
|
59061
59085
|
LogEvent.ONCHAINOS_CLI_ERROR,
|
|
59062
59086
|
parseErr,
|
|
@@ -60181,7 +60205,7 @@ function buildConnectParams(config, instanceId, protocolVersion) {
|
|
|
60181
60205
|
client: {
|
|
60182
60206
|
id: "gateway-client",
|
|
60183
60207
|
displayName: "okx-a2a-node",
|
|
60184
|
-
version: "0.2.
|
|
60208
|
+
version: "0.2.4-beta-e7a52faf6f-260811185020",
|
|
60185
60209
|
platform: "node",
|
|
60186
60210
|
mode: "backend",
|
|
60187
60211
|
instanceId
|
|
@@ -60192,7 +60216,7 @@ function buildConnectParams(config, instanceId, protocolVersion) {
|
|
|
60192
60216
|
commands: [],
|
|
60193
60217
|
permissions: {},
|
|
60194
60218
|
locale: Intl.DateTimeFormat().resolvedOptions().locale || "en-US",
|
|
60195
|
-
userAgent: `okx-a2a-node/${"0.2.
|
|
60219
|
+
userAgent: `okx-a2a-node/${"0.2.4-beta-e7a52faf6f-260811185020"}`,
|
|
60196
60220
|
auth: {
|
|
60197
60221
|
...config.token ? { token: config.token } : {},
|
|
60198
60222
|
...config.password ? { password: config.password } : {}
|
|
@@ -63621,7 +63645,7 @@ async function handleDaemonCommand(command, params) {
|
|
|
63621
63645
|
const payload = await handleXmtpDebugCommand(command, params.service);
|
|
63622
63646
|
return { ok: true, payload };
|
|
63623
63647
|
}
|
|
63624
|
-
const refresh = await params.service.refreshAgents();
|
|
63648
|
+
const refresh = await (params.refreshAgents?.() ?? params.service.refreshAgents());
|
|
63625
63649
|
return {
|
|
63626
63650
|
ok: true,
|
|
63627
63651
|
payload: {
|
|
@@ -65974,6 +65998,113 @@ var DEFAULT_OFFLINE_REPLAY_INTERVAL_SEC = 300;
|
|
|
65974
65998
|
var DEFAULT_XMTP_CLIENT_RECYCLE_INTERVAL_SEC = 6 * 60 * 60;
|
|
65975
65999
|
var XMTP_CLIENT_RECYCLE_INTERVAL_ENV = "OKX_A2A_XMTP_CLIENT_RECYCLE_INTERVAL_SEC";
|
|
65976
66000
|
var HEARTBEAT_GATEWAY_CHECK_TIMEOUT_MS = 2e3;
|
|
66001
|
+
async function runHeartbeatRefreshCycle(options) {
|
|
66002
|
+
const heartbeat = await timeSettled(options.heartbeat);
|
|
66003
|
+
const refreshAllowed = heartbeat.value === "performed" || heartbeat.value === "refresh_safe";
|
|
66004
|
+
const refresh = options.refresh && refreshAllowed ? await timeSettled(options.refresh) : void 0;
|
|
66005
|
+
return { heartbeat, refresh };
|
|
66006
|
+
}
|
|
66007
|
+
var AgentRefreshAuthGate = class {
|
|
66008
|
+
authBlocked = false;
|
|
66009
|
+
get blocked() {
|
|
66010
|
+
return this.authBlocked;
|
|
66011
|
+
}
|
|
66012
|
+
recordSuccess() {
|
|
66013
|
+
this.authBlocked = false;
|
|
66014
|
+
}
|
|
66015
|
+
recordFailure(err) {
|
|
66016
|
+
if (!isOnchainosAuthError(err)) {
|
|
66017
|
+
return false;
|
|
66018
|
+
}
|
|
66019
|
+
this.authBlocked = true;
|
|
66020
|
+
return true;
|
|
66021
|
+
}
|
|
66022
|
+
};
|
|
66023
|
+
var AgentRefreshCoordinator = class {
|
|
66024
|
+
constructor(options) {
|
|
66025
|
+
this.options = options;
|
|
66026
|
+
}
|
|
66027
|
+
options;
|
|
66028
|
+
authGate = new AgentRefreshAuthGate();
|
|
66029
|
+
get blocked() {
|
|
66030
|
+
return this.authGate.blocked;
|
|
66031
|
+
}
|
|
66032
|
+
async lookup(previousFingerprint) {
|
|
66033
|
+
const wasBlocked = this.authGate.blocked;
|
|
66034
|
+
try {
|
|
66035
|
+
const result = await this.options.lookup(previousFingerprint);
|
|
66036
|
+
this.authGate.recordSuccess();
|
|
66037
|
+
if (wasBlocked) {
|
|
66038
|
+
this.options.onAuthRecovered?.();
|
|
66039
|
+
}
|
|
66040
|
+
return result;
|
|
66041
|
+
} catch (err) {
|
|
66042
|
+
if (this.authGate.recordFailure(err) && !wasBlocked) {
|
|
66043
|
+
this.options.onAuthBlocked?.();
|
|
66044
|
+
}
|
|
66045
|
+
throw err;
|
|
66046
|
+
}
|
|
66047
|
+
}
|
|
66048
|
+
async runScheduled() {
|
|
66049
|
+
if (this.options.isStopping() || this.authGate.blocked) {
|
|
66050
|
+
return null;
|
|
66051
|
+
}
|
|
66052
|
+
return this.options.refresh();
|
|
66053
|
+
}
|
|
66054
|
+
async runManual() {
|
|
66055
|
+
return this.options.refresh();
|
|
66056
|
+
}
|
|
66057
|
+
};
|
|
66058
|
+
var ListenerDeferredTaskScheduler = class {
|
|
66059
|
+
timers = /* @__PURE__ */ new Set();
|
|
66060
|
+
schedule(task) {
|
|
66061
|
+
const timer = setTimeout(() => {
|
|
66062
|
+
this.timers.delete(timer);
|
|
66063
|
+
task();
|
|
66064
|
+
}, 0);
|
|
66065
|
+
this.timers.add(timer);
|
|
66066
|
+
}
|
|
66067
|
+
cancelAll() {
|
|
66068
|
+
for (const timer of this.timers) {
|
|
66069
|
+
clearTimeout(timer);
|
|
66070
|
+
}
|
|
66071
|
+
this.timers.clear();
|
|
66072
|
+
}
|
|
66073
|
+
};
|
|
66074
|
+
var ListenerMaintenanceGate = class {
|
|
66075
|
+
inFlight = null;
|
|
66076
|
+
offlineReplayPending = false;
|
|
66077
|
+
xmtpRecyclePending = false;
|
|
66078
|
+
tryEnter(task) {
|
|
66079
|
+
if (task !== "xmtp_recycle" && this.xmtpRecyclePending || this.inFlight) {
|
|
66080
|
+
if (task === "offline_replay") {
|
|
66081
|
+
this.offlineReplayPending = true;
|
|
66082
|
+
} else if (task === "xmtp_recycle") {
|
|
66083
|
+
this.xmtpRecyclePending = true;
|
|
66084
|
+
}
|
|
66085
|
+
return false;
|
|
66086
|
+
}
|
|
66087
|
+
if (task === "xmtp_recycle") {
|
|
66088
|
+
this.xmtpRecyclePending = false;
|
|
66089
|
+
}
|
|
66090
|
+
this.inFlight = task;
|
|
66091
|
+
return true;
|
|
66092
|
+
}
|
|
66093
|
+
leave(task) {
|
|
66094
|
+
if (this.inFlight !== task) {
|
|
66095
|
+
return null;
|
|
66096
|
+
}
|
|
66097
|
+
this.inFlight = null;
|
|
66098
|
+
if (this.xmtpRecyclePending) {
|
|
66099
|
+
return "xmtp_recycle";
|
|
66100
|
+
}
|
|
66101
|
+
if (this.offlineReplayPending) {
|
|
66102
|
+
this.offlineReplayPending = false;
|
|
66103
|
+
return "offline_replay";
|
|
66104
|
+
}
|
|
66105
|
+
return null;
|
|
66106
|
+
}
|
|
66107
|
+
};
|
|
65977
66108
|
var UPGRADE_RECOMMENDATION_IDEMPOTENCY_KEY = "system:onchainos-offline-replay-upgrade";
|
|
65978
66109
|
function resolveOfflineReplayIntervalSec(systemConfig) {
|
|
65979
66110
|
const interval = systemConfig.offlineReplayInterval;
|
|
@@ -66173,10 +66304,24 @@ async function runListenerWithLock(options, paths) {
|
|
|
66173
66304
|
}
|
|
66174
66305
|
});
|
|
66175
66306
|
logWithTimestamp("[okx-agent-task] user_attention watcher coordinator scanning SQLite watcher state");
|
|
66307
|
+
let stopping = false;
|
|
66176
66308
|
const service = XmtpService.getInstance();
|
|
66309
|
+
const agentRefreshCoordinator = new AgentRefreshCoordinator({
|
|
66310
|
+
lookup: (previousFingerprint) => listAllAgentsWithMetadata(previousFingerprint),
|
|
66311
|
+
refresh: () => service.refreshAgents(),
|
|
66312
|
+
isStopping: () => stopping,
|
|
66313
|
+
onAuthBlocked: () => {
|
|
66314
|
+
logWithTimestamp(
|
|
66315
|
+
"[okx-agent-task] agent refresh auth blocked; periodic agent get paused. After wallet login, run `okx-a2a agent refresh` or restart the daemon"
|
|
66316
|
+
);
|
|
66317
|
+
},
|
|
66318
|
+
onAuthRecovered: () => {
|
|
66319
|
+
logWithTimestamp("[okx-agent-task] agent refresh auth recovered; periodic refresh resumed");
|
|
66320
|
+
}
|
|
66321
|
+
});
|
|
66177
66322
|
service.setDataDir(paths.xmtpDir);
|
|
66178
66323
|
service.setTools({
|
|
66179
|
-
listAllAgentsWithMetadata:
|
|
66324
|
+
listAllAgentsWithMetadata: (previousFingerprint) => agentRefreshCoordinator.lookup(previousFingerprint),
|
|
66180
66325
|
fetchSensitiveWords: async () => fetchSensitiveWords(),
|
|
66181
66326
|
fetchSystemConfig: async () => fetchSystemConfig({
|
|
66182
66327
|
notifySessionExpired: (command) => service.tools.notifySessionExpired?.(command)
|
|
@@ -66203,7 +66348,7 @@ async function runListenerWithLock(options, paths) {
|
|
|
66203
66348
|
}
|
|
66204
66349
|
}),
|
|
66205
66350
|
notifySessionExpired: (command) => {
|
|
66206
|
-
const rawText = `The onchainos login session has expired while running ${command}. Run \`onchainos wallet login\`
|
|
66351
|
+
const rawText = `The onchainos login session has expired while running ${command}. Run \`onchainos wallet login\`, then \`okx-a2a agent refresh\` or restart \`okx-a2a\`.`;
|
|
66207
66352
|
void store.appendBackup(buildSystemStoredMessage({
|
|
66208
66353
|
reason: "onchainos-session-expired",
|
|
66209
66354
|
rawText,
|
|
@@ -66231,12 +66376,12 @@ async function runListenerWithLock(options, paths) {
|
|
|
66231
66376
|
});
|
|
66232
66377
|
}
|
|
66233
66378
|
});
|
|
66234
|
-
service.setPluginVersion("0.2.
|
|
66379
|
+
service.setPluginVersion("0.2.4-beta-e7a52faf6f-260811185020");
|
|
66235
66380
|
await service.init();
|
|
66236
66381
|
const pluginVersionStatus = service.pluginVersionStatus;
|
|
66237
66382
|
if (pluginVersionStatus.unavailable) {
|
|
66238
66383
|
throw new Error(
|
|
66239
|
-
`@okxweb3/a2a-node v${"0.2.
|
|
66384
|
+
`@okxweb3/a2a-node v${"0.2.4-beta-e7a52faf6f-260811185020"} is below the required minimum v${pluginVersionStatus.minVersion}`
|
|
66240
66385
|
);
|
|
66241
66386
|
}
|
|
66242
66387
|
const systemConfig = service.getSystemConfig();
|
|
@@ -66254,7 +66399,7 @@ async function runListenerWithLock(options, paths) {
|
|
|
66254
66399
|
onchainosAgentId: "*",
|
|
66255
66400
|
reason: "system-config missing sentryDsn",
|
|
66256
66401
|
pluginId: "@okxweb3/a2a-node",
|
|
66257
|
-
pluginVersion: "0.2.
|
|
66402
|
+
pluginVersion: "0.2.4-beta-e7a52faf6f-260811185020"
|
|
66258
66403
|
});
|
|
66259
66404
|
}
|
|
66260
66405
|
logWithTimestamp(
|
|
@@ -66266,37 +66411,56 @@ async function runListenerWithLock(options, paths) {
|
|
|
66266
66411
|
logWithTimestamp(
|
|
66267
66412
|
`[okx-agent-task] startup replay complete clients=${startupReplaySummary.clients} replayed=${startupReplaySummary.replayed} skipped=${startupReplaySummary.skipped} duration=${startupReplaySummary.durationMs}ms`
|
|
66268
66413
|
);
|
|
66269
|
-
let maintenanceInFlight = null;
|
|
66270
66414
|
let lastRecycleReplayAtMs = 0;
|
|
66271
|
-
|
|
66272
|
-
const
|
|
66273
|
-
|
|
66274
|
-
|
|
66415
|
+
const maintenanceGate = new ListenerMaintenanceGate();
|
|
66416
|
+
const deferredMaintenanceTasks = new ListenerDeferredTaskScheduler();
|
|
66417
|
+
const leaveMaintenanceTask = (task) => {
|
|
66418
|
+
const pendingTask = maintenanceGate.leave(task);
|
|
66419
|
+
if (stopping) {
|
|
66420
|
+
return;
|
|
66275
66421
|
}
|
|
66276
|
-
if (
|
|
66277
|
-
|
|
66422
|
+
if (pendingTask === "xmtp_recycle") {
|
|
66423
|
+
deferredMaintenanceTasks.schedule(() => void xmtpRecycleTick());
|
|
66424
|
+
} else if (pendingTask === "offline_replay") {
|
|
66425
|
+
deferredMaintenanceTasks.schedule(() => void offlineReplayTick());
|
|
66278
66426
|
}
|
|
66279
|
-
if (task === "xmtp_recycle") {
|
|
66280
|
-
xmtpRecyclePending = false;
|
|
66281
|
-
}
|
|
66282
|
-
maintenanceInFlight = task;
|
|
66283
|
-
return true;
|
|
66284
66427
|
};
|
|
66285
|
-
const
|
|
66286
|
-
if (
|
|
66287
|
-
|
|
66288
|
-
|
|
66289
|
-
|
|
66428
|
+
const syncTick = async () => {
|
|
66429
|
+
if (stopping || agentRefreshCoordinator.blocked) {
|
|
66430
|
+
return;
|
|
66431
|
+
}
|
|
66432
|
+
if (!maintenanceGate.tryEnter("sync")) {
|
|
66433
|
+
return;
|
|
66434
|
+
}
|
|
66435
|
+
const tickStartedAt = Date.now();
|
|
66436
|
+
try {
|
|
66437
|
+
const refresh = await agentRefreshCoordinator.runScheduled();
|
|
66438
|
+
if (!refresh) {
|
|
66439
|
+
return;
|
|
66290
66440
|
}
|
|
66441
|
+
logWithTimestamp(
|
|
66442
|
+
`[okx-agent-task] sync tick agents=${refresh.agentCount} changed=${refresh.changed ? "yes" : "no"} added=${refresh.added.length} removed=${refresh.removed.length}`
|
|
66443
|
+
);
|
|
66444
|
+
} catch (err) {
|
|
66445
|
+
logger.error(LogEvent.DAEMON_TICK_FAILED, err instanceof Error ? err : new Error(String(err)), {
|
|
66446
|
+
component: "node_listener",
|
|
66447
|
+
stage: "sync_tick",
|
|
66448
|
+
durationMs: String(Date.now() - tickStartedAt),
|
|
66449
|
+
reason: "sync_tick_exception"
|
|
66450
|
+
});
|
|
66451
|
+
logWithTimestamp(`[okx-agent-task] sync tick failed total=${Date.now() - tickStartedAt}ms:`, err);
|
|
66452
|
+
} finally {
|
|
66453
|
+
leaveMaintenanceTask("sync");
|
|
66291
66454
|
}
|
|
66292
66455
|
};
|
|
66293
|
-
|
|
66294
|
-
|
|
66295
|
-
|
|
66456
|
+
let heartbeatInFlight = false;
|
|
66457
|
+
const heartbeatTick = async () => {
|
|
66458
|
+
if (heartbeatInFlight || stopping) {
|
|
66459
|
+
return "blocked";
|
|
66296
66460
|
}
|
|
66461
|
+
heartbeatInFlight = true;
|
|
66297
66462
|
const tickStartedAt = Date.now();
|
|
66298
66463
|
try {
|
|
66299
|
-
const refresh = await service.refreshAgents();
|
|
66300
66464
|
const hasActiveAgents = service.getClients().size > 0;
|
|
66301
66465
|
let shouldHeartbeat = hasActiveAgents;
|
|
66302
66466
|
const heartbeatProvider = resolveConfiguredAiProvider({ store: sessionStore }) ?? detectGatewayInvocation();
|
|
@@ -66311,7 +66475,7 @@ async function runListenerWithLock(options, paths) {
|
|
|
66311
66475
|
new Error(`heartbeat gateway check failed: provider=hermes reason=${hermesStatus.reason}`),
|
|
66312
66476
|
{
|
|
66313
66477
|
component: "node_listener",
|
|
66314
|
-
stage: "
|
|
66478
|
+
stage: "heartbeat_tick",
|
|
66315
66479
|
reason: hermesStatus.reason ?? "unknown",
|
|
66316
66480
|
provider: "hermes",
|
|
66317
66481
|
hermesHome: hermesStatus.hermesHome,
|
|
@@ -66335,7 +66499,7 @@ async function runListenerWithLock(options, paths) {
|
|
|
66335
66499
|
new Error(`heartbeat skipped: provider=${heartbeatProvider ?? "(not set)"} gateway unavailable`),
|
|
66336
66500
|
{
|
|
66337
66501
|
component: "node_listener",
|
|
66338
|
-
stage: "
|
|
66502
|
+
stage: "heartbeat_tick",
|
|
66339
66503
|
reason: "gateway_unavailable",
|
|
66340
66504
|
provider: heartbeatProvider ?? "(not set)",
|
|
66341
66505
|
chainIndex: ONCHAINOS_CHAIN_INDEX,
|
|
@@ -66351,7 +66515,7 @@ async function runListenerWithLock(options, paths) {
|
|
|
66351
66515
|
new Error("heartbeat skipped: no active agents"),
|
|
66352
66516
|
{
|
|
66353
66517
|
component: "node_listener",
|
|
66354
|
-
stage: "
|
|
66518
|
+
stage: "heartbeat_tick",
|
|
66355
66519
|
reason: "no_active_agents",
|
|
66356
66520
|
provider: heartbeatProvider ?? "(not set)",
|
|
66357
66521
|
chainIndex: ONCHAINOS_CHAIN_INDEX
|
|
@@ -66364,7 +66528,7 @@ async function runListenerWithLock(options, paths) {
|
|
|
66364
66528
|
if (shouldHeartbeat && heartbeatResult.error) {
|
|
66365
66529
|
logger.error(LogEvent.HEARTBEAT_FAILED, heartbeatResult.error instanceof Error ? heartbeatResult.error : new Error(String(heartbeatResult.error)), {
|
|
66366
66530
|
component: "node_listener",
|
|
66367
|
-
stage: "
|
|
66531
|
+
stage: "heartbeat_tick",
|
|
66368
66532
|
reason: heartbeatResult.error instanceof Error ? heartbeatResult.error.name : "unknown_error",
|
|
66369
66533
|
durationMs: String(heartbeatMs),
|
|
66370
66534
|
chainIndex: ONCHAINOS_CHAIN_INDEX,
|
|
@@ -66372,23 +66536,27 @@ async function runListenerWithLock(options, paths) {
|
|
|
66372
66536
|
});
|
|
66373
66537
|
logWithTimestamp(`[okx-agent-task] heartbeat failed duration=${heartbeatMs}ms:`, heartbeatResult.error);
|
|
66374
66538
|
}
|
|
66375
|
-
|
|
66376
|
-
`[okx-agent-task] sync tick agents=${refresh.agentCount} changed=${refresh.changed ? "yes" : "no"} added=${refresh.added.length} removed=${refresh.removed.length}`
|
|
66377
|
-
);
|
|
66539
|
+
return shouldHeartbeat ? "performed" : "refresh_safe";
|
|
66378
66540
|
} catch (err) {
|
|
66379
|
-
logger.error(LogEvent.
|
|
66541
|
+
logger.error(LogEvent.HEARTBEAT_FAILED, err instanceof Error ? err : new Error(String(err)), {
|
|
66380
66542
|
component: "node_listener",
|
|
66381
|
-
stage: "
|
|
66543
|
+
stage: "heartbeat_tick",
|
|
66382
66544
|
durationMs: String(Date.now() - tickStartedAt),
|
|
66383
|
-
reason: "
|
|
66545
|
+
reason: "heartbeat_tick_exception",
|
|
66546
|
+
chainIndex: ONCHAINOS_CHAIN_INDEX,
|
|
66547
|
+
communicationClass: "onchainos_or_network"
|
|
66384
66548
|
});
|
|
66385
|
-
logWithTimestamp(`[okx-agent-task]
|
|
66549
|
+
logWithTimestamp(`[okx-agent-task] heartbeat tick failed total=${Date.now() - tickStartedAt}ms:`, err);
|
|
66550
|
+
return "blocked";
|
|
66386
66551
|
} finally {
|
|
66387
|
-
|
|
66552
|
+
heartbeatInFlight = false;
|
|
66388
66553
|
}
|
|
66389
66554
|
};
|
|
66390
66555
|
const offlineReplayTick = async () => {
|
|
66391
|
-
if (
|
|
66556
|
+
if (stopping) {
|
|
66557
|
+
return;
|
|
66558
|
+
}
|
|
66559
|
+
if (!maintenanceGate.tryEnter("offline_replay")) {
|
|
66392
66560
|
return;
|
|
66393
66561
|
}
|
|
66394
66562
|
const tickStartedAt = Date.now();
|
|
@@ -66430,8 +66598,10 @@ async function runListenerWithLock(options, paths) {
|
|
|
66430
66598
|
}
|
|
66431
66599
|
};
|
|
66432
66600
|
const xmtpRecycleTick = async () => {
|
|
66433
|
-
if (
|
|
66434
|
-
|
|
66601
|
+
if (stopping) {
|
|
66602
|
+
return;
|
|
66603
|
+
}
|
|
66604
|
+
if (!maintenanceGate.tryEnter("xmtp_recycle")) {
|
|
66435
66605
|
return;
|
|
66436
66606
|
}
|
|
66437
66607
|
const tickStartedAt = Date.now();
|
|
@@ -66475,7 +66645,6 @@ async function runListenerWithLock(options, paths) {
|
|
|
66475
66645
|
let timer;
|
|
66476
66646
|
let offlineReplayTimer;
|
|
66477
66647
|
let xmtpClientRecycleTimer;
|
|
66478
|
-
let stopping = false;
|
|
66479
66648
|
const scheduleSyncTimer = (nextIntervalSec) => {
|
|
66480
66649
|
if (stopping) {
|
|
66481
66650
|
return;
|
|
@@ -66486,7 +66655,10 @@ async function runListenerWithLock(options, paths) {
|
|
|
66486
66655
|
intervalSec = Math.max(10, nextIntervalSec);
|
|
66487
66656
|
logWithTimestamp(`[okx-agent-task] scheduled sync interval ${intervalSec}s`);
|
|
66488
66657
|
timer = setInterval(() => {
|
|
66489
|
-
void
|
|
66658
|
+
void runHeartbeatRefreshCycle({
|
|
66659
|
+
heartbeat: heartbeatTick,
|
|
66660
|
+
refresh: syncTick
|
|
66661
|
+
});
|
|
66490
66662
|
}, intervalSec * 1e3);
|
|
66491
66663
|
};
|
|
66492
66664
|
const scheduleOfflineReplayTimer = (nextIntervalSec) => {
|
|
@@ -66568,9 +66740,12 @@ async function runListenerWithLock(options, paths) {
|
|
|
66568
66740
|
const systemConfigRefreshTimer = setInterval(() => {
|
|
66569
66741
|
void refreshSystemConfigTick();
|
|
66570
66742
|
}, 60 * 60 * 1e3);
|
|
66571
|
-
void
|
|
66743
|
+
void runHeartbeatRefreshCycle({
|
|
66744
|
+
heartbeat: heartbeatTick
|
|
66745
|
+
});
|
|
66572
66746
|
const commandProcessor = startCommandProcessor({
|
|
66573
66747
|
service,
|
|
66748
|
+
refreshAgents: () => agentRefreshCoordinator.runManual(),
|
|
66574
66749
|
store,
|
|
66575
66750
|
sessionStore,
|
|
66576
66751
|
homeDir: options.homeDir
|
|
@@ -66589,6 +66764,7 @@ async function runListenerWithLock(options, paths) {
|
|
|
66589
66764
|
resolve11();
|
|
66590
66765
|
}, SHUTDOWN_FORCE_RESOLVE_MS);
|
|
66591
66766
|
void (async () => {
|
|
66767
|
+
deferredMaintenanceTasks.cancelAll();
|
|
66592
66768
|
if (timer) {
|
|
66593
66769
|
clearInterval(timer);
|
|
66594
66770
|
}
|
|
@@ -68900,7 +69076,7 @@ async function exportDiagnosticLogs(options) {
|
|
|
68900
69076
|
node: process.version,
|
|
68901
69077
|
platform: process.platform,
|
|
68902
69078
|
arch: process.arch,
|
|
68903
|
-
packageVersion: true ? "0.2.
|
|
69079
|
+
packageVersion: true ? "0.2.4-beta-e7a52faf6f-260811185020" : "unknown",
|
|
68904
69080
|
sensitiveContentIncluded: options.includeSensitiveContent,
|
|
68905
69081
|
listenerAndLlmContentIncluded: true,
|
|
68906
69082
|
credentialsAlwaysRedacted: true,
|
|
@@ -70736,7 +70912,7 @@ async function runDoctor(options = {}) {
|
|
|
70736
70912
|
platform: options.platform ?? process.platform,
|
|
70737
70913
|
env: options.env ?? process.env,
|
|
70738
70914
|
target: options.target ?? resolveDoctorTarget(options.env ?? process.env),
|
|
70739
|
-
cliVersion: options.cliVersion ?? (true ? "0.2.
|
|
70915
|
+
cliVersion: options.cliVersion ?? (true ? "0.2.4-beta-e7a52faf6f-260811185020" : "0.0.0"),
|
|
70740
70916
|
fixMode: options.fix === true,
|
|
70741
70917
|
nonInteractive: options.nonInteractive === true,
|
|
70742
70918
|
packageChanged: false,
|
|
@@ -70959,6 +71135,8 @@ init_autostart_windows();
|
|
|
70959
71135
|
0 && (module.exports = {
|
|
70960
71136
|
AI_PROVIDERS,
|
|
70961
71137
|
AgentMessageDirection,
|
|
71138
|
+
AgentRefreshAuthGate,
|
|
71139
|
+
AgentRefreshCoordinator,
|
|
70962
71140
|
AiRunner,
|
|
70963
71141
|
BACKUP_JOB_ID,
|
|
70964
71142
|
CODEX_APP_DIRS_ENV,
|
|
@@ -70978,6 +71156,8 @@ init_autostart_windows();
|
|
|
70978
71156
|
InboundReplayGate,
|
|
70979
71157
|
InvalidXmtpMessageStore,
|
|
70980
71158
|
JOB_PROVIDER_BINDING_SOURCES,
|
|
71159
|
+
ListenerDeferredTaskScheduler,
|
|
71160
|
+
ListenerMaintenanceGate,
|
|
70981
71161
|
LogEvent,
|
|
70982
71162
|
MESSAGE_ELIGIBLE_OFFLINE_REPLAY_FLAG,
|
|
70983
71163
|
MESSAGE_ELIGIBLE_OFFLINE_REPLAY_HELP_TOKEN,
|
|
@@ -71174,6 +71354,7 @@ init_autostart_windows();
|
|
|
71174
71354
|
resolveXmtpClientRecycleIntervalSec,
|
|
71175
71355
|
runAiAdapter,
|
|
71176
71356
|
runDoctor,
|
|
71357
|
+
runHeartbeatRefreshCycle,
|
|
71177
71358
|
runListener,
|
|
71178
71359
|
scanUserAttentionWatchers,
|
|
71179
71360
|
setOpenClawWebSocketFactoryForTests,
|
package/package.json
CHANGED