@okxweb3/a2a-node 0.2.0 → 0.2.1-beta-8ae7a0d300-260807181806
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 +905 -69
- package/dist/index.js +893 -64
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -19597,12 +19597,15 @@ var init_events = __esm({
|
|
|
19597
19597
|
INBOUND_DELIVERED: "Inbound delivered to session",
|
|
19598
19598
|
DM_DELIVERED: "DM delivered to session",
|
|
19599
19599
|
OUTBOUND_ELIGIBILITY_CHECKED: "Outbound eligibility checked",
|
|
19600
|
+
MESSAGE_ELIGIBILITY_CHECKED: "Message eligibility checked",
|
|
19600
19601
|
AGENT_CLIENT_CREATED: "Agent client created",
|
|
19601
19602
|
AGENT_INSTALLATION_SUMMARY: "Agent installation summary",
|
|
19602
19603
|
XMTP_HISTORY_SYNC_REQUESTED: "XMTP history sync requested",
|
|
19603
19604
|
XMTP_DEBUG_SYNC_REQUESTED: "XMTP debug sync requested",
|
|
19604
19605
|
XMTP_DEBUG_SYNC_COMPLETED: "XMTP debug sync completed",
|
|
19605
19606
|
AGENT_CLIENT_REMOVED: "Agent client removed",
|
|
19607
|
+
AGENT_STREAM_RECOVERED: "Agent stream recovered",
|
|
19608
|
+
AGENT_STREAM_RECOVERY_REPLAY_COMPLETED: "Agent stream recovery replay completed",
|
|
19606
19609
|
ADDRESS_SYNC_COMPLETED: "Address sync completed",
|
|
19607
19610
|
AGENT_REFRESH_SESSION_EXPIRED: "Agent refresh aborted: onchainos session expired, local clients taken offline",
|
|
19608
19611
|
OFFLINE_REPLAY_MESSAGE_REPLAYED: "Offline replay message replayed",
|
|
@@ -19637,6 +19640,8 @@ var init_events = __esm({
|
|
|
19637
19640
|
CONVERSATIONS_STREAM_FAILED: "conversations.stream failed",
|
|
19638
19641
|
AGENT_START_FAILED: "agent.start failed",
|
|
19639
19642
|
AGENT_STREAM_ERROR: "agent stream error",
|
|
19643
|
+
AGENT_UNHANDLED_ERROR: "Agent unhandled error",
|
|
19644
|
+
AGENT_STREAM_RECOVERY_TIMEOUT: "Agent stream recovery timeout",
|
|
19640
19645
|
BOOTSTRAP_FAILED: "Bootstrap failed",
|
|
19641
19646
|
ONCHAINOS_SESSION_EXPIRED: "Onchainos session expired",
|
|
19642
19647
|
ONCHAINOS_CLI_ERROR: "Onchainos CLI error",
|
|
@@ -19646,6 +19651,7 @@ var init_events = __esm({
|
|
|
19646
19651
|
MESSAGE_PARSE_FAILED: "Message parse failed",
|
|
19647
19652
|
MESSAGE_HANDLER_ERROR: "Message handler error",
|
|
19648
19653
|
INBOUND_DISPATCH_FAILED: "Inbound dispatch failed",
|
|
19654
|
+
INBOUND_REPLAY_GATE_DRAIN_FAILED: "Inbound replay gate drain failed",
|
|
19649
19655
|
// Default name stamped on events that reach Sentry without going through this
|
|
19650
19656
|
// logger — uncaught exceptions and unhandled rejections. Without it those
|
|
19651
19657
|
// events carry no eventName and cannot be classified.
|
|
@@ -19943,7 +19949,10 @@ var init_xmtp_test_metrics = __esm({
|
|
|
19943
19949
|
"Address sync completed",
|
|
19944
19950
|
"Agent client created",
|
|
19945
19951
|
"Agent client removed",
|
|
19946
|
-
"
|
|
19952
|
+
"agent stream error",
|
|
19953
|
+
"Agent stream recovered",
|
|
19954
|
+
"Agent stream recovery replay completed",
|
|
19955
|
+
"Agent stream recovery timeout",
|
|
19947
19956
|
"conversations.stream failed",
|
|
19948
19957
|
"Inbound delivered to session",
|
|
19949
19958
|
"Inbound dispatch failed",
|
|
@@ -19962,6 +19971,190 @@ var init_xmtp_test_metrics = __esm({
|
|
|
19962
19971
|
}
|
|
19963
19972
|
});
|
|
19964
19973
|
|
|
19974
|
+
// ../core/src/sentry-logger/error-diagnostics.ts
|
|
19975
|
+
function asErrorLike(value) {
|
|
19976
|
+
return value instanceof Error ? value : void 0;
|
|
19977
|
+
}
|
|
19978
|
+
function diagnosticToken(value) {
|
|
19979
|
+
if (typeof value !== "string" && typeof value !== "number") {
|
|
19980
|
+
return void 0;
|
|
19981
|
+
}
|
|
19982
|
+
const token = String(value).trim();
|
|
19983
|
+
if (!token || /^(?:null|undefined|unknown)$/i.test(token)) {
|
|
19984
|
+
return void 0;
|
|
19985
|
+
}
|
|
19986
|
+
if (!/^[A-Za-z0-9_.:-]+$/.test(token)) {
|
|
19987
|
+
return void 0;
|
|
19988
|
+
}
|
|
19989
|
+
return token.slice(0, MAX_DIAGNOSTIC_TOKEN_LENGTH);
|
|
19990
|
+
}
|
|
19991
|
+
function syscallToken(value) {
|
|
19992
|
+
if (typeof value !== "string") {
|
|
19993
|
+
return void 0;
|
|
19994
|
+
}
|
|
19995
|
+
const operation = diagnosticToken(value.trim().split(/\s+/, 1)[0])?.toLowerCase();
|
|
19996
|
+
return operation && KNOWN_SYSCALLS.has(operation) ? operation : void 0;
|
|
19997
|
+
}
|
|
19998
|
+
function knownErrorCode(value) {
|
|
19999
|
+
const code = diagnosticToken(value)?.toUpperCase();
|
|
20000
|
+
return code && KNOWN_ERROR_CODES.has(code) ? code : void 0;
|
|
20001
|
+
}
|
|
20002
|
+
function readCode(error) {
|
|
20003
|
+
return knownErrorCode(error?.code) ?? knownErrorCode(error?.errno);
|
|
20004
|
+
}
|
|
20005
|
+
function classifyError(error, code) {
|
|
20006
|
+
const normalizedCode = code?.toUpperCase();
|
|
20007
|
+
const name = error?.name.toLowerCase() ?? "";
|
|
20008
|
+
const message = error?.message.toLowerCase() ?? "";
|
|
20009
|
+
if (normalizedCode && RESOURCE_EXHAUSTED_CODES.has(normalizedCode)) {
|
|
20010
|
+
return "resource_exhausted";
|
|
20011
|
+
}
|
|
20012
|
+
if (normalizedCode && CONNECTION_INTERRUPTED_CODES.has(normalizedCode)) {
|
|
20013
|
+
return "connection_interrupted";
|
|
20014
|
+
}
|
|
20015
|
+
if (normalizedCode && NETWORK_UNAVAILABLE_CODES.has(normalizedCode)) {
|
|
20016
|
+
return "network_unavailable";
|
|
20017
|
+
}
|
|
20018
|
+
if (normalizedCode && TIMEOUT_CODES.has(normalizedCode)) {
|
|
20019
|
+
return "timeout";
|
|
20020
|
+
}
|
|
20021
|
+
if (normalizedCode && PERMISSION_CODES.has(normalizedCode)) {
|
|
20022
|
+
return "permission_denied";
|
|
20023
|
+
}
|
|
20024
|
+
if (normalizedCode === "ENOENT") {
|
|
20025
|
+
return "missing_dependency";
|
|
20026
|
+
}
|
|
20027
|
+
if (normalizedCode === "ABORT_ERR" || name === "aborterror") {
|
|
20028
|
+
return "cancelled";
|
|
20029
|
+
}
|
|
20030
|
+
if (name === "syntaxerror" || /(?:json|response).*(?:parse|invalid)/.test(message)) {
|
|
20031
|
+
return "invalid_response";
|
|
20032
|
+
}
|
|
20033
|
+
if (/session\s+(?:is\s+)?expired|login\s+expired/.test(message)) {
|
|
20034
|
+
return "session_expired";
|
|
20035
|
+
}
|
|
20036
|
+
if (/timed?\s*out|timeout/.test(message)) {
|
|
20037
|
+
return "timeout";
|
|
20038
|
+
}
|
|
20039
|
+
return "unknown";
|
|
20040
|
+
}
|
|
20041
|
+
function retryabilityFor(category) {
|
|
20042
|
+
switch (category) {
|
|
20043
|
+
case "connection_interrupted":
|
|
20044
|
+
case "network_unavailable":
|
|
20045
|
+
case "resource_exhausted":
|
|
20046
|
+
case "timeout":
|
|
20047
|
+
return "retryable";
|
|
20048
|
+
case "invalid_response":
|
|
20049
|
+
case "missing_dependency":
|
|
20050
|
+
case "permission_denied":
|
|
20051
|
+
case "session_expired":
|
|
20052
|
+
return "non_retryable";
|
|
20053
|
+
default:
|
|
20054
|
+
return "unknown";
|
|
20055
|
+
}
|
|
20056
|
+
}
|
|
20057
|
+
function causeChain(error) {
|
|
20058
|
+
const chain = [];
|
|
20059
|
+
const seen = /* @__PURE__ */ new Set();
|
|
20060
|
+
let current = error;
|
|
20061
|
+
while (current && chain.length < MAX_CAUSE_DEPTH && !seen.has(current)) {
|
|
20062
|
+
chain.push(current);
|
|
20063
|
+
seen.add(current);
|
|
20064
|
+
current = asErrorLike(current.cause);
|
|
20065
|
+
}
|
|
20066
|
+
return chain;
|
|
20067
|
+
}
|
|
20068
|
+
function buildErrorDiagnostics(eventName, error, existingExtra) {
|
|
20069
|
+
const errorLike = asErrorLike(error);
|
|
20070
|
+
const legacy = {};
|
|
20071
|
+
if (errorLike) {
|
|
20072
|
+
legacy.errorName = errorLike.name;
|
|
20073
|
+
legacy.errorMessageLength = String(errorLike.message.length);
|
|
20074
|
+
}
|
|
20075
|
+
if (!errorLike || eventName === LogEvent.AGENT_STREAM_ERROR) {
|
|
20076
|
+
return legacy;
|
|
20077
|
+
}
|
|
20078
|
+
const chain = causeChain(errorLike);
|
|
20079
|
+
const primary = chain[0];
|
|
20080
|
+
const cause = chain.length > 1 ? chain[chain.length - 1] : void 0;
|
|
20081
|
+
const fallbackExitCode = diagnosticToken(existingExtra.exitCode);
|
|
20082
|
+
const primaryCode = readCode(primary);
|
|
20083
|
+
const primaryCategory = classifyError(primary, primaryCode);
|
|
20084
|
+
const primarySyscall = syscallToken(primary.syscall);
|
|
20085
|
+
const causeCode = readCode(cause);
|
|
20086
|
+
const causeCategory = cause ? classifyError(cause, causeCode) : void 0;
|
|
20087
|
+
const causeSyscall = syscallToken(cause?.syscall);
|
|
20088
|
+
const classifiedCategory = primaryCategory === "unknown" && causeCategory ? causeCategory : primaryCategory;
|
|
20089
|
+
const effectiveCategory = classifiedCategory === "unknown" && fallbackExitCode && fallbackExitCode !== "0" ? "process_exit" : classifiedCategory;
|
|
20090
|
+
const effectiveCode = primaryCode ?? causeCode;
|
|
20091
|
+
const effectiveSyscall = primarySyscall ?? causeSyscall;
|
|
20092
|
+
return {
|
|
20093
|
+
...legacy,
|
|
20094
|
+
errorCategory: effectiveCategory,
|
|
20095
|
+
errorRetryability: retryabilityFor(effectiveCategory),
|
|
20096
|
+
errorCauseDepth: String(Math.max(0, chain.length - 1)),
|
|
20097
|
+
...effectiveCode ? { errorCode: effectiveCode } : {},
|
|
20098
|
+
...effectiveSyscall ? { errorSyscall: effectiveSyscall } : {},
|
|
20099
|
+
...cause ? {
|
|
20100
|
+
causeErrorMessageLength: String(cause.message.length),
|
|
20101
|
+
causeErrorCategory: causeCategory ?? "unknown",
|
|
20102
|
+
...causeCode ? { causeErrorCode: causeCode } : {},
|
|
20103
|
+
...causeSyscall ? { causeErrorSyscall: causeSyscall } : {}
|
|
20104
|
+
} : {}
|
|
20105
|
+
};
|
|
20106
|
+
}
|
|
20107
|
+
var MAX_DIAGNOSTIC_TOKEN_LENGTH, MAX_CAUSE_DEPTH, RESOURCE_EXHAUSTED_CODES, CONNECTION_INTERRUPTED_CODES, NETWORK_UNAVAILABLE_CODES, TIMEOUT_CODES, PERMISSION_CODES, KNOWN_ERROR_CODES, KNOWN_SYSCALLS;
|
|
20108
|
+
var init_error_diagnostics = __esm({
|
|
20109
|
+
"../core/src/sentry-logger/error-diagnostics.ts"() {
|
|
20110
|
+
"use strict";
|
|
20111
|
+
init_events();
|
|
20112
|
+
MAX_DIAGNOSTIC_TOKEN_LENGTH = 64;
|
|
20113
|
+
MAX_CAUSE_DEPTH = 4;
|
|
20114
|
+
RESOURCE_EXHAUSTED_CODES = /* @__PURE__ */ new Set(["EAGAIN", "EMFILE", "ENFILE", "ENOMEM"]);
|
|
20115
|
+
CONNECTION_INTERRUPTED_CODES = /* @__PURE__ */ new Set(["ECONNRESET", "EPIPE"]);
|
|
20116
|
+
NETWORK_UNAVAILABLE_CODES = /* @__PURE__ */ new Set([
|
|
20117
|
+
"EAI_AGAIN",
|
|
20118
|
+
"ECONNREFUSED",
|
|
20119
|
+
"EHOSTUNREACH",
|
|
20120
|
+
"ENETDOWN",
|
|
20121
|
+
"ENETUNREACH",
|
|
20122
|
+
"ENOTFOUND"
|
|
20123
|
+
]);
|
|
20124
|
+
TIMEOUT_CODES = /* @__PURE__ */ new Set(["ETIMEDOUT", "ESOCKETTIMEDOUT"]);
|
|
20125
|
+
PERMISSION_CODES = /* @__PURE__ */ new Set(["EACCES", "EPERM"]);
|
|
20126
|
+
KNOWN_ERROR_CODES = /* @__PURE__ */ new Set([
|
|
20127
|
+
...RESOURCE_EXHAUSTED_CODES,
|
|
20128
|
+
...CONNECTION_INTERRUPTED_CODES,
|
|
20129
|
+
...NETWORK_UNAVAILABLE_CODES,
|
|
20130
|
+
...TIMEOUT_CODES,
|
|
20131
|
+
...PERMISSION_CODES,
|
|
20132
|
+
"ABORT_ERR",
|
|
20133
|
+
"ENOENT"
|
|
20134
|
+
]);
|
|
20135
|
+
KNOWN_SYSCALLS = /* @__PURE__ */ new Set([
|
|
20136
|
+
"access",
|
|
20137
|
+
"bind",
|
|
20138
|
+
"close",
|
|
20139
|
+
"connect",
|
|
20140
|
+
"getaddrinfo",
|
|
20141
|
+
"kill",
|
|
20142
|
+
"listen",
|
|
20143
|
+
"mkdir",
|
|
20144
|
+
"open",
|
|
20145
|
+
"read",
|
|
20146
|
+
"readdir",
|
|
20147
|
+
"readlink",
|
|
20148
|
+
"rename",
|
|
20149
|
+
"rmdir",
|
|
20150
|
+
"spawn",
|
|
20151
|
+
"stat",
|
|
20152
|
+
"unlink",
|
|
20153
|
+
"write"
|
|
20154
|
+
]);
|
|
20155
|
+
}
|
|
20156
|
+
});
|
|
20157
|
+
|
|
19965
20158
|
// ../core/src/sentry-logger/index.ts
|
|
19966
20159
|
function applyFatalEventDefaults(event) {
|
|
19967
20160
|
try {
|
|
@@ -20007,6 +20200,7 @@ var init_sentry_logger = __esm({
|
|
|
20007
20200
|
init_events();
|
|
20008
20201
|
init_log_fields();
|
|
20009
20202
|
init_xmtp_test_metrics();
|
|
20203
|
+
init_error_diagnostics();
|
|
20010
20204
|
init_events();
|
|
20011
20205
|
init_log_fields();
|
|
20012
20206
|
FLOW_ID = (0, import_node_crypto3.randomUUID)();
|
|
@@ -20094,14 +20288,23 @@ var init_sentry_logger = __esm({
|
|
|
20094
20288
|
"agentId",
|
|
20095
20289
|
"agentPlatform",
|
|
20096
20290
|
"cacheName",
|
|
20291
|
+
"causeCode",
|
|
20292
|
+
"causeType",
|
|
20293
|
+
"causeVariant",
|
|
20097
20294
|
"checkpoint",
|
|
20098
20295
|
"code",
|
|
20099
20296
|
"communicationClass",
|
|
20100
20297
|
"component",
|
|
20101
20298
|
"eventFamily",
|
|
20102
20299
|
"eventName",
|
|
20300
|
+
"endpoint",
|
|
20301
|
+
"errorCategory",
|
|
20302
|
+
"errorCode",
|
|
20303
|
+
"errorRetryability",
|
|
20304
|
+
"errorSyscall",
|
|
20103
20305
|
"exitCode",
|
|
20104
20306
|
"fromAgentId",
|
|
20307
|
+
"grpcMethod",
|
|
20105
20308
|
"jobId",
|
|
20106
20309
|
"kind",
|
|
20107
20310
|
"method",
|
|
@@ -20125,17 +20328,24 @@ var init_sentry_logger = __esm({
|
|
|
20125
20328
|
"source",
|
|
20126
20329
|
"stage",
|
|
20127
20330
|
"status",
|
|
20331
|
+
"streamErrorCode",
|
|
20332
|
+
"streamType",
|
|
20128
20333
|
"subcommand",
|
|
20129
20334
|
"systemEvent",
|
|
20130
20335
|
"taskId",
|
|
20131
20336
|
"taskMode",
|
|
20132
20337
|
"toAgentId",
|
|
20133
20338
|
"transport",
|
|
20339
|
+
"transportFailure",
|
|
20340
|
+
"transportProtocol",
|
|
20134
20341
|
"type",
|
|
20135
20342
|
"workloadClass"
|
|
20136
20343
|
]);
|
|
20137
20344
|
SENTRY_FINGERPRINT_KEYS = [
|
|
20138
20345
|
"eventName",
|
|
20346
|
+
"errorCategory",
|
|
20347
|
+
"errorCode",
|
|
20348
|
+
"errorSyscall",
|
|
20139
20349
|
"cacheName",
|
|
20140
20350
|
"component",
|
|
20141
20351
|
"method",
|
|
@@ -20183,6 +20393,7 @@ var init_sentry_logger = __esm({
|
|
|
20183
20393
|
LogEvent.HERMES_SESSION_ROUTE_BINDING,
|
|
20184
20394
|
LogEvent.INBOUND_BLOCKED_ADDRESS_MISMATCH,
|
|
20185
20395
|
LogEvent.INBOUND_BLOCKED_INELIGIBLE,
|
|
20396
|
+
LogEvent.MESSAGE_ELIGIBILITY_CHECKED,
|
|
20186
20397
|
LogEvent.INBOUND_BLOCKED_SENSITIVE,
|
|
20187
20398
|
LogEvent.INBOUND_DROP_DM_INVALID_PAYLOAD,
|
|
20188
20399
|
LogEvent.INBOUND_DROP_DM_NON_SYSTEM,
|
|
@@ -20198,6 +20409,9 @@ var init_sentry_logger = __esm({
|
|
|
20198
20409
|
LogEvent.MESSAGE_SENT,
|
|
20199
20410
|
LogEvent.AGENT_CLIENT_CREATED,
|
|
20200
20411
|
LogEvent.AGENT_CLIENT_REMOVED,
|
|
20412
|
+
LogEvent.AGENT_STREAM_ERROR,
|
|
20413
|
+
LogEvent.AGENT_STREAM_RECOVERED,
|
|
20414
|
+
LogEvent.AGENT_STREAM_RECOVERY_REPLAY_COMPLETED,
|
|
20201
20415
|
LogEvent.ADDRESS_SYNC_COMPLETED,
|
|
20202
20416
|
LogEvent.AGENTS_REFRESHED,
|
|
20203
20417
|
LogEvent.AGENTS_WAKEUP_NOTIFIED,
|
|
@@ -20329,19 +20543,24 @@ var init_sentry_logger = __esm({
|
|
|
20329
20543
|
}
|
|
20330
20544
|
captureError(message, error, extraWithFlow) {
|
|
20331
20545
|
try {
|
|
20546
|
+
const errorDiagnostics = buildErrorDiagnostics(
|
|
20547
|
+
message,
|
|
20548
|
+
error,
|
|
20549
|
+
extraWithFlow
|
|
20550
|
+
);
|
|
20551
|
+
const diagnosticExtra = {
|
|
20552
|
+
...extraWithFlow,
|
|
20553
|
+
...errorDiagnostics
|
|
20554
|
+
};
|
|
20332
20555
|
Sentry.withScope((scope) => {
|
|
20333
20556
|
scope.setLevel("error");
|
|
20334
|
-
_SentryLogger.applyDiagnostics(scope, message,
|
|
20557
|
+
_SentryLogger.applyDiagnostics(scope, message, diagnosticExtra);
|
|
20335
20558
|
Sentry.captureException(_SentryLogger.createSentryEvent(message), {
|
|
20336
20559
|
// eventName is unconditional: callers that pass no Error object are
|
|
20337
20560
|
// still classified events, and without it they reach SLS anonymous.
|
|
20338
20561
|
extra: {
|
|
20339
|
-
...
|
|
20340
|
-
eventName: message
|
|
20341
|
-
...error ? {
|
|
20342
|
-
errorName: error.name,
|
|
20343
|
-
errorMessageLength: String(error.message.length)
|
|
20344
|
-
} : {}
|
|
20562
|
+
...diagnosticExtra,
|
|
20563
|
+
eventName: message
|
|
20345
20564
|
}
|
|
20346
20565
|
});
|
|
20347
20566
|
});
|
|
@@ -30930,7 +31149,7 @@ var init_sentry_config = __esm({
|
|
|
30930
31149
|
environment = process.env.SENTRY_ENV === "dev" ? "dev" : "prod";
|
|
30931
31150
|
SENTRY_CONFIG = {
|
|
30932
31151
|
projectName: "okx/openclaw-okx-a2a-extension",
|
|
30933
|
-
release: "0.2.
|
|
31152
|
+
release: "0.2.1-beta-8ae7a0d300-260807181806",
|
|
30934
31153
|
environment,
|
|
30935
31154
|
runtimeContainer: normalizeRuntimeContainer(process.env.OKX_A2A_RUNTIME_CONTAINER)
|
|
30936
31155
|
};
|
|
@@ -31860,7 +32079,7 @@ async function getCurrentNodeCliVersion() {
|
|
|
31860
32079
|
return await getGlobalNpmPackageVersion(UPDATE_PACKAGES.node) ?? getBundledNodeCliVersion();
|
|
31861
32080
|
}
|
|
31862
32081
|
function getBundledNodeCliVersion() {
|
|
31863
|
-
return true ? "0.2.
|
|
32082
|
+
return true ? "0.2.1-beta-8ae7a0d300-260807181806" : null;
|
|
31864
32083
|
}
|
|
31865
32084
|
function readConfiguredAiProvider() {
|
|
31866
32085
|
const explicit = process.env.OKX_A2A_AI_PROVIDER || process.env.OKX_AGENT_TASK_AI_CLI;
|
|
@@ -32070,7 +32289,7 @@ async function updateHermes(release, options) {
|
|
|
32070
32289
|
}
|
|
32071
32290
|
}
|
|
32072
32291
|
async function installGatewayPluginForDoctor(target) {
|
|
32073
|
-
const release = isPrereleaseVersion("0.2.
|
|
32292
|
+
const release = isPrereleaseVersion("0.2.1-beta-8ae7a0d300-260807181806") ? "beta" : "latest";
|
|
32074
32293
|
const insideTargetGateway = detectGatewayInvocation() === target;
|
|
32075
32294
|
const options = {
|
|
32076
32295
|
restart: !insideTargetGateway,
|
|
@@ -42740,6 +42959,8 @@ __export(index_exports, {
|
|
|
42740
42959
|
HEARTBEAT_GATEWAY_CHECK_TIMEOUT_MS: () => HEARTBEAT_GATEWAY_CHECK_TIMEOUT_MS,
|
|
42741
42960
|
InboundReplayGate: () => InboundReplayGate,
|
|
42742
42961
|
InvalidXmtpMessageStore: () => InvalidXmtpMessageStore,
|
|
42962
|
+
MESSAGE_ELIGIBLE_OFFLINE_REPLAY_FLAG: () => MESSAGE_ELIGIBLE_OFFLINE_REPLAY_FLAG,
|
|
42963
|
+
MESSAGE_ELIGIBLE_OFFLINE_REPLAY_HELP_TOKEN: () => MESSAGE_ELIGIBLE_OFFLINE_REPLAY_HELP_TOKEN,
|
|
42743
42964
|
NATIVE_LAUNCHER_EXE_NAME: () => NATIVE_LAUNCHER_EXE_NAME,
|
|
42744
42965
|
OPENCLAW_GATEWAY_ROUTE_GROUP_ID: () => OPENCLAW_GATEWAY_ROUTE_GROUP_ID,
|
|
42745
42966
|
SYSTEM_NOTIFICATION_SESSION_KEY: () => SYSTEM_NOTIFICATION_SESSION_KEY,
|
|
@@ -42757,6 +42978,7 @@ __export(index_exports, {
|
|
|
42757
42978
|
XMTP_CLIENT_RECYCLE_INTERVAL_ENV: () => XMTP_CLIENT_RECYCLE_INTERVAL_ENV,
|
|
42758
42979
|
XmtpDm: () => Dm,
|
|
42759
42980
|
XmtpGroup: () => Group,
|
|
42981
|
+
XmtpService: () => XmtpService,
|
|
42760
42982
|
acquireDaemonLock: () => acquireDaemonLock,
|
|
42761
42983
|
activeDaemonPointerPath: () => activeDaemonPointerPath,
|
|
42762
42984
|
aiRunSentryExtra: () => aiRunSentryExtra,
|
|
@@ -42777,6 +42999,7 @@ __export(index_exports, {
|
|
|
42777
42999
|
buildInboundTerminalExtras: () => buildInboundTerminalExtras,
|
|
42778
43000
|
buildLaunchdPlist: () => buildLaunchdPlist,
|
|
42779
43001
|
buildLauncherEntryJs: () => buildLauncherEntryJs,
|
|
43002
|
+
buildMessageEligibleArgs: () => buildMessageEligibleArgs,
|
|
42780
43003
|
buildPendingConversationBackupDispatch: () => buildPendingConversationBackupDispatch,
|
|
42781
43004
|
buildSchtasksCreateArgs: () => buildSchtasksCreateArgs,
|
|
42782
43005
|
buildSchtasksDeleteArgs: () => buildSchtasksDeleteArgs,
|
|
@@ -42808,6 +43031,7 @@ __export(index_exports, {
|
|
|
42808
43031
|
detectAiProviders: () => detectAiProviders,
|
|
42809
43032
|
detectCurrentAiProvider: () => detectCurrentAiProvider,
|
|
42810
43033
|
detectGatewayInvocation: () => detectGatewayInvocation,
|
|
43034
|
+
detectMessageEligibleOfflineReplaySupport: () => detectMessageEligibleOfflineReplaySupport,
|
|
42811
43035
|
detectRuntime: () => detectRuntime,
|
|
42812
43036
|
ensureDaemonReady: () => ensureDaemonReady,
|
|
42813
43037
|
ensureDefaultAiProvider: () => ensureDefaultAiProvider,
|
|
@@ -42821,9 +43045,11 @@ __export(index_exports, {
|
|
|
42821
43045
|
findWindowsNativeOkxA2aExe: () => findWindowsNativeOkxA2aExe,
|
|
42822
43046
|
followFile: () => followFile,
|
|
42823
43047
|
formatDoctorReportForHumans: () => formatDoctorReportForHumans,
|
|
43048
|
+
getA2ACapabilities: () => getA2ACapabilities,
|
|
42824
43049
|
getDaemonStatus: () => getDaemonStatus,
|
|
42825
43050
|
getHermesGatewayPluginStatus: () => getHermesGatewayPluginStatus,
|
|
42826
43051
|
getSessionBusyTracker: () => getSessionBusyTracker,
|
|
43052
|
+
handleCapabilitiesCommand: () => handleCapabilitiesCommand,
|
|
42827
43053
|
handleDoctorCommand: () => handleDoctorCommand,
|
|
42828
43054
|
handleXmtpDebugCommand: () => handleXmtpDebugCommand,
|
|
42829
43055
|
handleXmtpSendCommand: () => handleXmtpSendCommand,
|
|
@@ -42837,6 +43063,7 @@ __export(index_exports, {
|
|
|
42837
43063
|
isDefaultTaskHome: () => isDefaultTaskHome,
|
|
42838
43064
|
isGatewayAvailableForHeartbeat: () => isGatewayAvailableForHeartbeat,
|
|
42839
43065
|
isHermesGatewayPluginEnabled: () => isHermesGatewayPluginEnabled,
|
|
43066
|
+
isOfflineReplayForTrigger: () => isOfflineReplayForTrigger,
|
|
42840
43067
|
isOpenClawA2aPluginAvailable: () => isOpenClawA2aPluginAvailable,
|
|
42841
43068
|
isOpenClawGatewayAvailable: () => isOpenClawGatewayAvailable,
|
|
42842
43069
|
isOriginalParentProcessAlive: () => isOriginalParentProcessAlive,
|
|
@@ -42848,6 +43075,8 @@ __export(index_exports, {
|
|
|
42848
43075
|
launchdPlistHasCurrentRestartPolicy: () => launchdPlistHasCurrentRestartPolicy,
|
|
42849
43076
|
logWinCompat: () => logWinCompat,
|
|
42850
43077
|
logXmtpMessageSent: () => logXmtpMessageSent,
|
|
43078
|
+
maybeRecommendOnchainosUpgrade: () => maybeRecommendOnchainosUpgrade,
|
|
43079
|
+
messageEligibleHelpAdvertisesOfflineReplay: () => messageEligibleHelpAdvertisesOfflineReplay,
|
|
42851
43080
|
nodeVersionSatisfies: () => nodeVersionSatisfies,
|
|
42852
43081
|
normalizeAiProvider: () => normalizeAiProvider,
|
|
42853
43082
|
normalizeHermesOkxA2aPluginConfig: () => normalizeHermesOkxA2aPluginConfig,
|
|
@@ -42873,6 +43102,7 @@ __export(index_exports, {
|
|
|
42873
43102
|
removeUserAttentionWatcher: () => removeUserAttentionWatcher,
|
|
42874
43103
|
reportDoctorRunToSentry: () => reportDoctorRunToSentry,
|
|
42875
43104
|
reportUserNotificationFailure: () => reportUserNotificationFailure,
|
|
43105
|
+
resetMessageEligibleOfflineReplayCapabilityForTests: () => resetMessageEligibleOfflineReplayCapabilityForTests,
|
|
42876
43106
|
resetResolvedOnchainosBinForTests: () => resetResolvedOnchainosBinForTests,
|
|
42877
43107
|
resolveAiPermissionPreset: () => resolveAiPermissionPreset,
|
|
42878
43108
|
resolveAiProviderCommand: () => resolveAiProviderCommand,
|
|
@@ -42884,6 +43114,7 @@ __export(index_exports, {
|
|
|
42884
43114
|
resolveDoctorTarget: () => resolveDoctorTarget,
|
|
42885
43115
|
resolveEnvelopePayload: () => resolveEnvelopePayload,
|
|
42886
43116
|
resolveNpmCmdShimScript: () => resolveNpmCmdShimScript,
|
|
43117
|
+
resolveOfflineReplayCapabilityMarker: () => resolveOfflineReplayCapabilityMarker,
|
|
42887
43118
|
resolveOfflineReplayIntervalSec: () => resolveOfflineReplayIntervalSec,
|
|
42888
43119
|
resolveOpenClawGatewayConfig: () => resolveOpenClawGatewayConfig,
|
|
42889
43120
|
resolveOpenClawGatewayRoute: () => resolveOpenClawGatewayRoute,
|
|
@@ -53982,6 +54213,165 @@ var cache = new LimitedMap(1e3);
|
|
|
53982
54213
|
// ../core/src/xmtp-sdk/index.ts
|
|
53983
54214
|
init_sentry_logger();
|
|
53984
54215
|
|
|
54216
|
+
// ../core/src/xmtp-sdk/stream-recovery-telemetry.ts
|
|
54217
|
+
function isAgentStreamRecoveryError(error) {
|
|
54218
|
+
return error instanceof Error && error.constructor.name === "AgentStreamingError" && typeof error.code === "number" && [1002, 1004, 1005].includes(error.code);
|
|
54219
|
+
}
|
|
54220
|
+
var TRANSPORT_FAILURE_PATTERNS = [
|
|
54221
|
+
[/broken\s*pipe|BrokenPipe/i, "broken_pipe"],
|
|
54222
|
+
[/connection\s*reset|ConnectionReset/i, "connection_reset"],
|
|
54223
|
+
[/timed?\s*out|TimedOut/i, "timeout"],
|
|
54224
|
+
[/unexpected\s*eof|UnexpectedEof/i, "unexpected_eof"]
|
|
54225
|
+
];
|
|
54226
|
+
var KNOWN_CAUSE_CODES = /* @__PURE__ */ new Set(["GenericFailure"]);
|
|
54227
|
+
var KNOWN_CAUSE_KINDS = /* @__PURE__ */ new Map([
|
|
54228
|
+
["SubscribeError::BoxError", ["SubscribeError", "BoxError"]]
|
|
54229
|
+
]);
|
|
54230
|
+
var KNOWN_GRPC_METHODS = /* @__PURE__ */ new Set([
|
|
54231
|
+
"SubscribeGroupMessages",
|
|
54232
|
+
"SubscribeWelcomeMessages"
|
|
54233
|
+
]);
|
|
54234
|
+
function extractStreamErrorTelemetry(error) {
|
|
54235
|
+
const telemetry = {};
|
|
54236
|
+
if (typeof error.code === "number" && Number.isSafeInteger(error.code)) {
|
|
54237
|
+
telemetry.streamErrorCode = String(error.code);
|
|
54238
|
+
const streamType = {
|
|
54239
|
+
1002: "conversation",
|
|
54240
|
+
1004: "message",
|
|
54241
|
+
1005: "setup"
|
|
54242
|
+
};
|
|
54243
|
+
if (streamType[error.code]) {
|
|
54244
|
+
telemetry.streamType = streamType[error.code];
|
|
54245
|
+
}
|
|
54246
|
+
}
|
|
54247
|
+
const cause = error.cause;
|
|
54248
|
+
if (!(cause instanceof Error)) {
|
|
54249
|
+
return telemetry;
|
|
54250
|
+
}
|
|
54251
|
+
telemetry.causeMessageLength = String(cause.message.length);
|
|
54252
|
+
const causeCode = cause.code;
|
|
54253
|
+
if (typeof causeCode === "string" && KNOWN_CAUSE_CODES.has(causeCode)) {
|
|
54254
|
+
telemetry.causeCode = causeCode;
|
|
54255
|
+
}
|
|
54256
|
+
const causeKind = cause.message.match(
|
|
54257
|
+
/^\[([A-Za-z][A-Za-z0-9]{0,63})::([A-Za-z][A-Za-z0-9]{0,63})\]/
|
|
54258
|
+
);
|
|
54259
|
+
const knownCauseKind = causeKind ? KNOWN_CAUSE_KINDS.get(`${causeKind[1]}::${causeKind[2]}`) : void 0;
|
|
54260
|
+
if (knownCauseKind) {
|
|
54261
|
+
telemetry.causeType = knownCauseKind[0];
|
|
54262
|
+
telemetry.causeVariant = knownCauseKind[1];
|
|
54263
|
+
}
|
|
54264
|
+
const grpcMethod = cause.message.match(
|
|
54265
|
+
/endpoint\s+["']\/[A-Za-z0-9_.]+\/([A-Za-z][A-Za-z0-9_]{0,63})["']/
|
|
54266
|
+
);
|
|
54267
|
+
if (grpcMethod && KNOWN_GRPC_METHODS.has(grpcMethod[1])) {
|
|
54268
|
+
telemetry.grpcMethod = grpcMethod[1];
|
|
54269
|
+
telemetry.endpoint = grpcMethod[1];
|
|
54270
|
+
}
|
|
54271
|
+
if (/\bh2 protocol error\b/i.test(cause.message)) {
|
|
54272
|
+
telemetry.transportProtocol = "h2";
|
|
54273
|
+
}
|
|
54274
|
+
const transportFailure = TRANSPORT_FAILURE_PATTERNS.find(
|
|
54275
|
+
([pattern]) => pattern.test(cause.message)
|
|
54276
|
+
);
|
|
54277
|
+
if (transportFailure) {
|
|
54278
|
+
telemetry.transportFailure = transportFailure[1];
|
|
54279
|
+
telemetry.reason = transportFailure[1];
|
|
54280
|
+
}
|
|
54281
|
+
return telemetry;
|
|
54282
|
+
}
|
|
54283
|
+
var StreamRecoveryTelemetry = class {
|
|
54284
|
+
nextSequence = 1;
|
|
54285
|
+
activeRecovery;
|
|
54286
|
+
get activeSequence() {
|
|
54287
|
+
return this.activeRecovery?.sequence;
|
|
54288
|
+
}
|
|
54289
|
+
markError(nowMs = Date.now()) {
|
|
54290
|
+
if (this.activeRecovery) {
|
|
54291
|
+
return {
|
|
54292
|
+
recoverySequence: this.activeRecovery.sequence,
|
|
54293
|
+
alreadyRecovering: true
|
|
54294
|
+
};
|
|
54295
|
+
}
|
|
54296
|
+
const sequence = this.nextSequence++;
|
|
54297
|
+
this.activeRecovery = { sequence, startedAtMs: nowMs };
|
|
54298
|
+
return { recoverySequence: sequence, alreadyRecovering: false };
|
|
54299
|
+
}
|
|
54300
|
+
markStarted(nowMs = Date.now()) {
|
|
54301
|
+
if (!this.activeRecovery) {
|
|
54302
|
+
return void 0;
|
|
54303
|
+
}
|
|
54304
|
+
const completed = {
|
|
54305
|
+
recoverySequence: this.activeRecovery.sequence,
|
|
54306
|
+
recoveryDurationMs: Math.max(0, nowMs - this.activeRecovery.startedAtMs)
|
|
54307
|
+
};
|
|
54308
|
+
this.activeRecovery = void 0;
|
|
54309
|
+
return completed;
|
|
54310
|
+
}
|
|
54311
|
+
cancel() {
|
|
54312
|
+
this.activeRecovery = void 0;
|
|
54313
|
+
}
|
|
54314
|
+
};
|
|
54315
|
+
var KeyedSingleFlight = class {
|
|
54316
|
+
inFlight = /* @__PURE__ */ new Map();
|
|
54317
|
+
run(key, discriminator, operation) {
|
|
54318
|
+
const normalizedKey = key.toLowerCase();
|
|
54319
|
+
const state = this.inFlight.get(normalizedKey);
|
|
54320
|
+
if (!state) {
|
|
54321
|
+
const active = createKeyedFlight(discriminator, operation);
|
|
54322
|
+
this.inFlight.set(normalizedKey, { active, queued: [] });
|
|
54323
|
+
this.execute(normalizedKey, active);
|
|
54324
|
+
return active.promise;
|
|
54325
|
+
}
|
|
54326
|
+
if (state.active.discriminator === discriminator) {
|
|
54327
|
+
return state.active.promise;
|
|
54328
|
+
}
|
|
54329
|
+
const queued = state.queued.find(
|
|
54330
|
+
(flight2) => flight2.discriminator === discriminator
|
|
54331
|
+
);
|
|
54332
|
+
if (queued) {
|
|
54333
|
+
return queued.promise;
|
|
54334
|
+
}
|
|
54335
|
+
const flight = createKeyedFlight(discriminator, operation);
|
|
54336
|
+
state.queued.push(flight);
|
|
54337
|
+
return flight.promise;
|
|
54338
|
+
}
|
|
54339
|
+
execute(key, flight) {
|
|
54340
|
+
void Promise.resolve().then(flight.operation).then(
|
|
54341
|
+
(value) => {
|
|
54342
|
+
flight.resolve(value);
|
|
54343
|
+
this.advance(key, flight);
|
|
54344
|
+
},
|
|
54345
|
+
(error) => {
|
|
54346
|
+
flight.reject(error);
|
|
54347
|
+
this.advance(key, flight);
|
|
54348
|
+
}
|
|
54349
|
+
);
|
|
54350
|
+
}
|
|
54351
|
+
advance(key, completed) {
|
|
54352
|
+
const state = this.inFlight.get(key);
|
|
54353
|
+
if (state?.active !== completed) {
|
|
54354
|
+
return;
|
|
54355
|
+
}
|
|
54356
|
+
const next = state.queued.shift();
|
|
54357
|
+
if (!next) {
|
|
54358
|
+
this.inFlight.delete(key);
|
|
54359
|
+
return;
|
|
54360
|
+
}
|
|
54361
|
+
state.active = next;
|
|
54362
|
+
this.execute(key, next);
|
|
54363
|
+
}
|
|
54364
|
+
};
|
|
54365
|
+
function createKeyedFlight(discriminator, operation) {
|
|
54366
|
+
let resolve11;
|
|
54367
|
+
let reject;
|
|
54368
|
+
const promise = new Promise((resolvePromise, rejectPromise) => {
|
|
54369
|
+
resolve11 = resolvePromise;
|
|
54370
|
+
reject = rejectPromise;
|
|
54371
|
+
});
|
|
54372
|
+
return { discriminator, operation, promise, resolve: resolve11, reject };
|
|
54373
|
+
}
|
|
54374
|
+
|
|
53985
54375
|
// ../core/src/xmtp-sdk/extract-job-id.ts
|
|
53986
54376
|
function extractJobIdFromContent(content) {
|
|
53987
54377
|
const raw = typeof content === "string" ? content : stringifyJsonForEnvelope(content);
|
|
@@ -54588,10 +54978,11 @@ var InboundReplayGate = class {
|
|
|
54588
54978
|
this.inbound = inbound;
|
|
54589
54979
|
}
|
|
54590
54980
|
inbound;
|
|
54591
|
-
|
|
54981
|
+
holds = 1;
|
|
54592
54982
|
queue = [];
|
|
54983
|
+
drainInFlight;
|
|
54593
54984
|
middleware = async (ctx, next) => {
|
|
54594
|
-
if (!this.
|
|
54985
|
+
if (this.holds === 0 && !this.drainInFlight) {
|
|
54595
54986
|
await this.inbound(ctx, next);
|
|
54596
54987
|
return;
|
|
54597
54988
|
}
|
|
@@ -54600,19 +54991,55 @@ var InboundReplayGate = class {
|
|
|
54600
54991
|
get bufferedCount() {
|
|
54601
54992
|
return this.queue.length;
|
|
54602
54993
|
}
|
|
54994
|
+
abandonFailedAndRelease() {
|
|
54995
|
+
const abandoned = this.queue.length > 0 ? 1 : 0;
|
|
54996
|
+
if (abandoned > 0) {
|
|
54997
|
+
this.queue.shift();
|
|
54998
|
+
}
|
|
54999
|
+
if (this.holds > 0) {
|
|
55000
|
+
this.holds--;
|
|
55001
|
+
}
|
|
55002
|
+
return abandoned;
|
|
55003
|
+
}
|
|
55004
|
+
hold() {
|
|
55005
|
+
this.holds++;
|
|
55006
|
+
}
|
|
54603
55007
|
async drain() {
|
|
55008
|
+
if (this.holds > 0) {
|
|
55009
|
+
this.holds--;
|
|
55010
|
+
}
|
|
55011
|
+
return this.drainReleased();
|
|
55012
|
+
}
|
|
55013
|
+
async drainReleased() {
|
|
55014
|
+
if (this.holds > 0) {
|
|
55015
|
+
return 0;
|
|
55016
|
+
}
|
|
55017
|
+
if (this.drainInFlight) {
|
|
55018
|
+
return this.drainInFlight;
|
|
55019
|
+
}
|
|
55020
|
+
const drain = Promise.resolve().then(() => this.drainQueue());
|
|
55021
|
+
this.drainInFlight = drain;
|
|
55022
|
+
try {
|
|
55023
|
+
return await drain;
|
|
55024
|
+
} finally {
|
|
55025
|
+
if (this.drainInFlight === drain) {
|
|
55026
|
+
this.drainInFlight = void 0;
|
|
55027
|
+
}
|
|
55028
|
+
}
|
|
55029
|
+
}
|
|
55030
|
+
async drainQueue() {
|
|
54604
55031
|
let drained = 0;
|
|
54605
|
-
while (this.queue.length > 0) {
|
|
55032
|
+
while (this.holds === 0 && this.queue.length > 0) {
|
|
54606
55033
|
const item = this.queue.shift();
|
|
54607
55034
|
try {
|
|
54608
55035
|
await this.inbound(item.ctx, item.next);
|
|
54609
55036
|
} catch (err) {
|
|
54610
55037
|
this.queue.unshift(item);
|
|
55038
|
+
this.holds = Math.max(1, this.holds);
|
|
54611
55039
|
throw err;
|
|
54612
55040
|
}
|
|
54613
55041
|
drained++;
|
|
54614
55042
|
}
|
|
54615
|
-
this.buffering = false;
|
|
54616
55043
|
return drained;
|
|
54617
55044
|
}
|
|
54618
55045
|
};
|
|
@@ -54628,6 +55055,9 @@ var SYSTEM_CONFIG_DEFAULTS = {
|
|
|
54628
55055
|
}
|
|
54629
55056
|
}
|
|
54630
55057
|
};
|
|
55058
|
+
var STREAM_RECOVERY_ALERT_THRESHOLD_MS = 3e4;
|
|
55059
|
+
var REPLAY_GATE_DRAIN_MAX_ATTEMPTS = 3;
|
|
55060
|
+
var REPLAY_GATE_DRAIN_RETRY_DELAY_MS = 100;
|
|
54631
55061
|
var SEMVER_RE = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*)?$/;
|
|
54632
55062
|
function normalizeSemverInput(v) {
|
|
54633
55063
|
return v.trim().replace(/^v/, "");
|
|
@@ -54808,6 +55238,9 @@ function parseGroupPayload(content) {
|
|
|
54808
55238
|
return null;
|
|
54809
55239
|
}
|
|
54810
55240
|
}
|
|
55241
|
+
function isOfflineReplayForTrigger(trigger) {
|
|
55242
|
+
return trigger === "startup";
|
|
55243
|
+
}
|
|
54811
55244
|
var XmtpService = class _XmtpService {
|
|
54812
55245
|
static instance = null;
|
|
54813
55246
|
env = process.env.XMTP_ENV ?? "production";
|
|
@@ -54833,7 +55266,11 @@ var XmtpService = class _XmtpService {
|
|
|
54833
55266
|
};
|
|
54834
55267
|
dataDir = DEFAULT_DATA_DIR;
|
|
54835
55268
|
syncByAddress = /* @__PURE__ */ new Map();
|
|
55269
|
+
offlineReplaySingleFlight = new KeyedSingleFlight();
|
|
54836
55270
|
inboundReplayGates = /* @__PURE__ */ new Map();
|
|
55271
|
+
streamRecoveryCleanupByAddress = /* @__PURE__ */ new Map();
|
|
55272
|
+
nextClientGeneration = 1;
|
|
55273
|
+
clientGenerationByClient = /* @__PURE__ */ new WeakMap();
|
|
54837
55274
|
agentListFingerprint;
|
|
54838
55275
|
// Only one refreshAgents can be in flight at a time; concurrent calls
|
|
54839
55276
|
// coalesce onto the same promise. This avoids duplicate Agent.create()
|
|
@@ -55288,6 +55725,7 @@ var XmtpService = class _XmtpService {
|
|
|
55288
55725
|
const client = this.clients.get(address);
|
|
55289
55726
|
if (client) {
|
|
55290
55727
|
try {
|
|
55728
|
+
this.cancelStreamRecoveryForAddress(address);
|
|
55291
55729
|
this.stoppedAddresses.add(address.toLowerCase());
|
|
55292
55730
|
client.stop();
|
|
55293
55731
|
logWithTimestamp(
|
|
@@ -55461,7 +55899,10 @@ var XmtpService = class _XmtpService {
|
|
|
55461
55899
|
logWithTimestamp(
|
|
55462
55900
|
`[xmtp-sdk] refresh: ${address} has a prior sync timestamp, triggering offline replay`
|
|
55463
55901
|
);
|
|
55464
|
-
void this.
|
|
55902
|
+
void this.replayOfflineMessagesForAddressSingleFlight(
|
|
55903
|
+
address,
|
|
55904
|
+
"agent_refresh"
|
|
55905
|
+
).catch((err) => {
|
|
55465
55906
|
logWithTimestamp(`[xmtp-sdk] refresh: ${address} offline replay failed:`, err);
|
|
55466
55907
|
logger.error(
|
|
55467
55908
|
LogEvent.OFFLINE_REPLAY_FAILED,
|
|
@@ -55503,6 +55944,7 @@ var XmtpService = class _XmtpService {
|
|
|
55503
55944
|
}
|
|
55504
55945
|
const addressKey = address.toLowerCase();
|
|
55505
55946
|
try {
|
|
55947
|
+
this.cancelStreamRecoveryForAddress(address);
|
|
55506
55948
|
this.stoppedAddresses.add(addressKey);
|
|
55507
55949
|
await Promise.resolve(oldClient.stop());
|
|
55508
55950
|
this.clients.delete(address);
|
|
@@ -55561,7 +56003,10 @@ var XmtpService = class _XmtpService {
|
|
|
55561
56003
|
await this.startListeningForAddresses([address]);
|
|
55562
56004
|
let replaySummary;
|
|
55563
56005
|
try {
|
|
55564
|
-
replaySummary = await this.
|
|
56006
|
+
replaySummary = await this.replayOfflineMessagesForAddressSingleFlight(
|
|
56007
|
+
address,
|
|
56008
|
+
"client_recycle"
|
|
56009
|
+
);
|
|
55565
56010
|
} finally {
|
|
55566
56011
|
await this.drainInboundReplayGate(address);
|
|
55567
56012
|
}
|
|
@@ -55571,6 +56016,7 @@ var XmtpService = class _XmtpService {
|
|
|
55571
56016
|
recycled++;
|
|
55572
56017
|
} catch (err) {
|
|
55573
56018
|
failed++;
|
|
56019
|
+
this.cancelStreamRecoveryForAddress(address);
|
|
55574
56020
|
this.clients.delete(address);
|
|
55575
56021
|
logWithTimestamp(`[xmtp-sdk] recycle: failed to recreate client: ${address}`, err);
|
|
55576
56022
|
logger.error(
|
|
@@ -55971,16 +56417,80 @@ var XmtpService = class _XmtpService {
|
|
|
55971
56417
|
async startListening() {
|
|
55972
56418
|
await this.startListeningForAddresses([...this.clients.keys()]);
|
|
55973
56419
|
}
|
|
55974
|
-
async drainInboundReplayGate(address) {
|
|
56420
|
+
async drainInboundReplayGate(address, expectedGate) {
|
|
55975
56421
|
const gate = this.inboundReplayGates.get(address.toLowerCase());
|
|
55976
|
-
if (!gate) {
|
|
56422
|
+
if (!gate || expectedGate && gate !== expectedGate) {
|
|
55977
56423
|
return 0;
|
|
55978
56424
|
}
|
|
55979
|
-
|
|
56425
|
+
let attempt = 0;
|
|
56426
|
+
let totalDrained = 0;
|
|
56427
|
+
let releaseHold = true;
|
|
56428
|
+
while (true) {
|
|
56429
|
+
try {
|
|
56430
|
+
const drained = releaseHold ? await gate.drain() : await gate.drainReleased();
|
|
56431
|
+
totalDrained += drained;
|
|
56432
|
+
logWithTimestamp(
|
|
56433
|
+
`[xmtp-sdk:${address}] replay barrier released, buffered=${totalDrained} attempt=${attempt + 1}`
|
|
56434
|
+
);
|
|
56435
|
+
return totalDrained;
|
|
56436
|
+
} catch (err) {
|
|
56437
|
+
attempt++;
|
|
56438
|
+
logWithTimestamp(
|
|
56439
|
+
`[xmtp-sdk:${address}] replay barrier drain failed attempt=${attempt}/${REPLAY_GATE_DRAIN_MAX_ATTEMPTS}:`,
|
|
56440
|
+
err
|
|
56441
|
+
);
|
|
56442
|
+
if (attempt < REPLAY_GATE_DRAIN_MAX_ATTEMPTS) {
|
|
56443
|
+
releaseHold = true;
|
|
56444
|
+
await new Promise(
|
|
56445
|
+
(resolve11) => setTimeout(resolve11, REPLAY_GATE_DRAIN_RETRY_DELAY_MS * attempt)
|
|
56446
|
+
);
|
|
56447
|
+
continue;
|
|
56448
|
+
}
|
|
56449
|
+
const abandoned = gate.abandonFailedAndRelease();
|
|
56450
|
+
logger.error(
|
|
56451
|
+
LogEvent.INBOUND_REPLAY_GATE_DRAIN_FAILED,
|
|
56452
|
+
err instanceof Error ? err : void 0,
|
|
56453
|
+
{
|
|
56454
|
+
walletAddress: address,
|
|
56455
|
+
attemptCount: String(REPLAY_GATE_DRAIN_MAX_ATTEMPTS),
|
|
56456
|
+
abandonedCount: String(abandoned),
|
|
56457
|
+
stage: "inboundReplayGate/fail-open",
|
|
56458
|
+
reason: "drain_retry_exhausted"
|
|
56459
|
+
}
|
|
56460
|
+
);
|
|
56461
|
+
logWithTimestamp(
|
|
56462
|
+
`[xmtp-sdk:${address}] replay barrier fail-open after ${REPLAY_GATE_DRAIN_MAX_ATTEMPTS} failed attempts, abandoned=${abandoned}`
|
|
56463
|
+
);
|
|
56464
|
+
attempt = 0;
|
|
56465
|
+
releaseHold = false;
|
|
56466
|
+
}
|
|
56467
|
+
}
|
|
56468
|
+
}
|
|
56469
|
+
holdInboundReplayGate(address) {
|
|
56470
|
+
const gate = this.inboundReplayGates.get(address.toLowerCase());
|
|
56471
|
+
if (!gate) {
|
|
56472
|
+
return void 0;
|
|
56473
|
+
}
|
|
56474
|
+
gate.hold();
|
|
55980
56475
|
logWithTimestamp(
|
|
55981
|
-
`[xmtp-sdk:${address}]
|
|
56476
|
+
`[xmtp-sdk:${address}] replay barrier held, buffered=${gate.bufferedCount}`
|
|
55982
56477
|
);
|
|
55983
|
-
return
|
|
56478
|
+
return gate;
|
|
56479
|
+
}
|
|
56480
|
+
cancelStreamRecoveryForAddress(address) {
|
|
56481
|
+
const addressKey = address.toLowerCase();
|
|
56482
|
+
const cleanup = this.streamRecoveryCleanupByAddress.get(addressKey);
|
|
56483
|
+
this.streamRecoveryCleanupByAddress.delete(addressKey);
|
|
56484
|
+
cleanup?.();
|
|
56485
|
+
}
|
|
56486
|
+
getClientGeneration(client) {
|
|
56487
|
+
const existing = this.clientGenerationByClient.get(client);
|
|
56488
|
+
if (existing !== void 0) {
|
|
56489
|
+
return existing;
|
|
56490
|
+
}
|
|
56491
|
+
const generation = this.nextClientGeneration++;
|
|
56492
|
+
this.clientGenerationByClient.set(client, generation);
|
|
56493
|
+
return generation;
|
|
55984
56494
|
}
|
|
55985
56495
|
notifyAgentsWakeupAfterReplay() {
|
|
55986
56496
|
const notifyAgentsWakeup2 = this.tools.notifyAgentsWakeup;
|
|
@@ -56014,7 +56524,7 @@ var XmtpService = class _XmtpService {
|
|
|
56014
56524
|
* cannot overtake the stored backlog.
|
|
56015
56525
|
*/
|
|
56016
56526
|
async completeStartupReplay() {
|
|
56017
|
-
const summary = await this.replayOfflineMessages();
|
|
56527
|
+
const summary = await this.replayOfflineMessages("startup");
|
|
56018
56528
|
for (const address of this.clients.keys()) {
|
|
56019
56529
|
await this.drainInboundReplayGate(address);
|
|
56020
56530
|
}
|
|
@@ -56025,6 +56535,8 @@ var XmtpService = class _XmtpService {
|
|
|
56025
56535
|
const valid = addresses.filter((addr) => this.clients.has(addr));
|
|
56026
56536
|
await parallelMap(valid, async (address) => {
|
|
56027
56537
|
const agent = this.clients.get(address);
|
|
56538
|
+
const clientGeneration = this.getClientGeneration(agent);
|
|
56539
|
+
const addressKey = address.toLowerCase();
|
|
56028
56540
|
const tag = `[xmtp-sdk:${address}]`;
|
|
56029
56541
|
const onchainosAgent = this.getAgentByAddress(address);
|
|
56030
56542
|
const identity = {
|
|
@@ -56127,14 +56639,131 @@ var XmtpService = class _XmtpService {
|
|
|
56127
56639
|
logWithTimestamp(`${tag} reconnecting in ${delay}ms (attempt=${attempt + 1})`);
|
|
56128
56640
|
setTimeout(() => void startWithRetry(attempt + 1), delay);
|
|
56129
56641
|
};
|
|
56642
|
+
const streamRecovery = new StreamRecoveryTelemetry();
|
|
56643
|
+
let recoveryTimeout;
|
|
56644
|
+
let pendingRecoveryGate;
|
|
56645
|
+
let recoveryDisposed = false;
|
|
56646
|
+
this.cancelStreamRecoveryForAddress(address);
|
|
56647
|
+
const cleanupStreamRecovery = () => {
|
|
56648
|
+
recoveryDisposed = true;
|
|
56649
|
+
streamRecovery.cancel();
|
|
56650
|
+
if (recoveryTimeout) {
|
|
56651
|
+
clearTimeout(recoveryTimeout);
|
|
56652
|
+
recoveryTimeout = void 0;
|
|
56653
|
+
}
|
|
56654
|
+
};
|
|
56655
|
+
this.streamRecoveryCleanupByAddress.set(
|
|
56656
|
+
addressKey,
|
|
56657
|
+
cleanupStreamRecovery
|
|
56658
|
+
);
|
|
56130
56659
|
agent.on("unhandledError", (err) => {
|
|
56660
|
+
if (recoveryDisposed || this.clients.get(address) !== agent || this.stoppedAddresses.has(addressKey)) {
|
|
56661
|
+
return;
|
|
56662
|
+
}
|
|
56663
|
+
if (!isAgentStreamRecoveryError(err)) {
|
|
56664
|
+
logWithTimestamp(`${tag} agent unhandled error:`, err);
|
|
56665
|
+
logger.error(LogEvent.AGENT_UNHANDLED_ERROR, err, agentExtras(identity));
|
|
56666
|
+
return;
|
|
56667
|
+
}
|
|
56668
|
+
const recovery = streamRecovery.markError();
|
|
56669
|
+
const errorTelemetry = extractStreamErrorTelemetry(err);
|
|
56670
|
+
if (!recovery.alreadyRecovering) {
|
|
56671
|
+
pendingRecoveryGate = this.holdInboundReplayGate(address);
|
|
56672
|
+
}
|
|
56131
56673
|
logWithTimestamp(`${tag} agent stream error:`, err);
|
|
56132
|
-
logger.
|
|
56674
|
+
logger.info(LogEvent.AGENT_STREAM_ERROR, {
|
|
56675
|
+
...agentExtras(identity),
|
|
56676
|
+
...errorTelemetry,
|
|
56677
|
+
clientGeneration: String(clientGeneration),
|
|
56678
|
+
recoverySequence: String(recovery.recoverySequence),
|
|
56679
|
+
recoveryAlreadyActive: String(recovery.alreadyRecovering)
|
|
56680
|
+
});
|
|
56681
|
+
if (!recovery.alreadyRecovering) {
|
|
56682
|
+
recoveryTimeout = setTimeout(() => {
|
|
56683
|
+
if (recoveryDisposed || this.clients.get(address) !== agent || this.stoppedAddresses.has(addressKey) || streamRecovery.activeSequence !== recovery.recoverySequence) {
|
|
56684
|
+
return;
|
|
56685
|
+
}
|
|
56686
|
+
logger.error(LogEvent.AGENT_STREAM_RECOVERY_TIMEOUT, void 0, {
|
|
56687
|
+
...agentExtras(identity),
|
|
56688
|
+
...errorTelemetry,
|
|
56689
|
+
clientGeneration: String(clientGeneration),
|
|
56690
|
+
recoverySequence: String(recovery.recoverySequence),
|
|
56691
|
+
recoveryDurationMs: String(STREAM_RECOVERY_ALERT_THRESHOLD_MS),
|
|
56692
|
+
thresholdMs: String(STREAM_RECOVERY_ALERT_THRESHOLD_MS)
|
|
56693
|
+
});
|
|
56694
|
+
}, STREAM_RECOVERY_ALERT_THRESHOLD_MS);
|
|
56695
|
+
}
|
|
56133
56696
|
});
|
|
56134
56697
|
agent.on("start", () => {
|
|
56698
|
+
if (recoveryDisposed || this.clients.get(address) !== agent || this.stoppedAddresses.has(addressKey)) {
|
|
56699
|
+
return;
|
|
56700
|
+
}
|
|
56701
|
+
const recovery = streamRecovery.markStarted();
|
|
56702
|
+
if (recoveryTimeout) {
|
|
56703
|
+
clearTimeout(recoveryTimeout);
|
|
56704
|
+
recoveryTimeout = void 0;
|
|
56705
|
+
}
|
|
56135
56706
|
logWithTimestamp(
|
|
56136
56707
|
`${tag} agent stream started agentId=${identity.onchainosAgentId ?? "(unknown)"} inboxId=${identity.inboxId ?? "(unknown)"} role=${identity.role ?? "(unknown)"} consentStates=Allowed,Unknown lastSync=${formatLogTimestamp2(this.syncByAddress.get(address))}`
|
|
56137
56708
|
);
|
|
56709
|
+
if (recovery) {
|
|
56710
|
+
const recoveryGate = pendingRecoveryGate;
|
|
56711
|
+
pendingRecoveryGate = void 0;
|
|
56712
|
+
logger.info(LogEvent.AGENT_STREAM_RECOVERED, {
|
|
56713
|
+
...agentExtras(identity),
|
|
56714
|
+
clientGeneration: String(clientGeneration),
|
|
56715
|
+
recoverySequence: String(recovery.recoverySequence),
|
|
56716
|
+
recoveryDurationMs: String(recovery.recoveryDurationMs)
|
|
56717
|
+
});
|
|
56718
|
+
void (async () => {
|
|
56719
|
+
try {
|
|
56720
|
+
const summary = await this.replayOfflineMessagesForAddressSingleFlight(
|
|
56721
|
+
address,
|
|
56722
|
+
"stream_recovery",
|
|
56723
|
+
`${clientGeneration}:${recovery.recoverySequence}`
|
|
56724
|
+
);
|
|
56725
|
+
if (!recoveryDisposed && this.clients.get(address) === agent) {
|
|
56726
|
+
logger.info(LogEvent.AGENT_STREAM_RECOVERY_REPLAY_COMPLETED, {
|
|
56727
|
+
...agentExtras(identity),
|
|
56728
|
+
clientGeneration: String(clientGeneration),
|
|
56729
|
+
recoverySequence: String(recovery.recoverySequence),
|
|
56730
|
+
replayed: String(summary.replayed),
|
|
56731
|
+
skipped: String(summary.skipped),
|
|
56732
|
+
conversationCount: String(summary.conversations),
|
|
56733
|
+
replayDurationMs: String(summary.durationMs)
|
|
56734
|
+
});
|
|
56735
|
+
}
|
|
56736
|
+
} catch (err) {
|
|
56737
|
+
logWithTimestamp(`${tag} recovery offline replay failed:`, err);
|
|
56738
|
+
logger.error(
|
|
56739
|
+
LogEvent.OFFLINE_REPLAY_FAILED,
|
|
56740
|
+
err instanceof Error ? err : new Error(String(err)),
|
|
56741
|
+
{
|
|
56742
|
+
...agentExtras(identity),
|
|
56743
|
+
clientGeneration: String(clientGeneration),
|
|
56744
|
+
recoverySequence: String(recovery.recoverySequence),
|
|
56745
|
+
stage: "streamRecovery/replay"
|
|
56746
|
+
}
|
|
56747
|
+
);
|
|
56748
|
+
} finally {
|
|
56749
|
+
try {
|
|
56750
|
+
await this.drainInboundReplayGate(address, recoveryGate);
|
|
56751
|
+
} catch (err) {
|
|
56752
|
+
logWithTimestamp(`${tag} recovery replay gate drain failed:`, err);
|
|
56753
|
+
logger.error(
|
|
56754
|
+
LogEvent.OFFLINE_REPLAY_FAILED,
|
|
56755
|
+
err instanceof Error ? err : new Error(String(err)),
|
|
56756
|
+
{
|
|
56757
|
+
...agentExtras(identity),
|
|
56758
|
+
clientGeneration: String(clientGeneration),
|
|
56759
|
+
recoverySequence: String(recovery.recoverySequence),
|
|
56760
|
+
stage: "streamRecovery/drain-gate"
|
|
56761
|
+
}
|
|
56762
|
+
);
|
|
56763
|
+
}
|
|
56764
|
+
}
|
|
56765
|
+
})();
|
|
56766
|
+
}
|
|
56138
56767
|
if (process.env.XMTP_FORCE_DEBUG === "true") {
|
|
56139
56768
|
void logDetails(agent).catch((err) => {
|
|
56140
56769
|
logWithTimestamp(`${tag} agent debug details failed:`, err);
|
|
@@ -56152,9 +56781,10 @@ var XmtpService = class _XmtpService {
|
|
|
56152
56781
|
logWithTimestamp(`${tag} message listener started`);
|
|
56153
56782
|
});
|
|
56154
56783
|
}
|
|
56155
|
-
async replayOfflineMessagesForAddress(address) {
|
|
56784
|
+
async replayOfflineMessagesForAddress(address, trigger = "periodic_repair") {
|
|
56156
56785
|
const addressReplayStartedAt = Date.now();
|
|
56157
56786
|
const summary = createOfflineReplayAddressSummary(address);
|
|
56787
|
+
const isOfflineReplay = isOfflineReplayForTrigger(trigger);
|
|
56158
56788
|
const agent = this.clients.get(address);
|
|
56159
56789
|
if (!agent) {
|
|
56160
56790
|
summary.durationMs = Date.now() - addressReplayStartedAt;
|
|
@@ -56278,7 +56908,8 @@ var XmtpService = class _XmtpService {
|
|
|
56278
56908
|
};
|
|
56279
56909
|
const handleStartedAt = Date.now();
|
|
56280
56910
|
const handled = await processOffline(fakeCtx, handlerDeps, {
|
|
56281
|
-
skipNotify: true
|
|
56911
|
+
skipNotify: true,
|
|
56912
|
+
isOfflineReplay
|
|
56282
56913
|
});
|
|
56283
56914
|
const handleMs = Date.now() - handleStartedAt;
|
|
56284
56915
|
summary.handleMs += handleMs;
|
|
@@ -56360,14 +56991,28 @@ var XmtpService = class _XmtpService {
|
|
|
56360
56991
|
);
|
|
56361
56992
|
return summary;
|
|
56362
56993
|
}
|
|
56363
|
-
|
|
56994
|
+
replayOfflineMessagesForAddressSingleFlight(address, trigger = "periodic_repair", recoveryIdentity) {
|
|
56995
|
+
const eligibilityClass = trigger === "stream_recovery" ? `stream_recovery:${recoveryIdentity ?? "unknown"}` : isOfflineReplayForTrigger(trigger) ? "startup_offline" : "online_repair";
|
|
56996
|
+
return this.offlineReplaySingleFlight.run(
|
|
56997
|
+
address,
|
|
56998
|
+
eligibilityClass,
|
|
56999
|
+
async () => {
|
|
57000
|
+
await this._backupReady;
|
|
57001
|
+
return this.replayOfflineMessagesForAddress(address, trigger);
|
|
57002
|
+
}
|
|
57003
|
+
);
|
|
57004
|
+
}
|
|
57005
|
+
async replayOfflineMessages(trigger = "periodic_repair") {
|
|
56364
57006
|
await this._backupReady;
|
|
56365
57007
|
const replayStartedAt = Date.now();
|
|
56366
57008
|
let totalReplayed = 0;
|
|
56367
57009
|
let totalSkipped = 0;
|
|
56368
57010
|
const addresses = [];
|
|
56369
57011
|
for (const address of this.clients.keys()) {
|
|
56370
|
-
const summary2 = await this.
|
|
57012
|
+
const summary2 = await this.replayOfflineMessagesForAddressSingleFlight(
|
|
57013
|
+
address,
|
|
57014
|
+
trigger
|
|
57015
|
+
);
|
|
56371
57016
|
addresses.push(summary2);
|
|
56372
57017
|
const { replayed, skipped: skipped2 } = summary2;
|
|
56373
57018
|
totalReplayed += replayed;
|
|
@@ -56705,7 +57350,7 @@ async function exec(args) {
|
|
|
56705
57350
|
);
|
|
56706
57351
|
logger.error(
|
|
56707
57352
|
LogEvent.ONCHAINOS_CLI_ERROR,
|
|
56708
|
-
new Error("onchainos command failed"),
|
|
57353
|
+
err instanceof Error ? err : new Error("onchainos command failed"),
|
|
56709
57354
|
{
|
|
56710
57355
|
component: "onchainos_cli",
|
|
56711
57356
|
source: "onchainos",
|
|
@@ -56808,6 +57453,107 @@ function reportSessionExpired(command) {
|
|
|
56808
57453
|
);
|
|
56809
57454
|
}
|
|
56810
57455
|
|
|
57456
|
+
// ../core/src/xmtp-sdk/onchainos/offline-replay-capability.ts
|
|
57457
|
+
init_log();
|
|
57458
|
+
var MESSAGE_ELIGIBLE_OFFLINE_REPLAY_FLAG = "--is-offline-replay";
|
|
57459
|
+
var MESSAGE_ELIGIBLE_OFFLINE_REPLAY_HELP_TOKEN = "is-offline-replay";
|
|
57460
|
+
var UPGRADE_RECOMMENDATION_PAIR_KEY = "onchainos:message-eligible-offline-replay";
|
|
57461
|
+
var UPGRADE_RECOMMENDATION_REASON = "OnchainOS does not support the offline-replay eligibility argument; using the legacy message-eligible contract.";
|
|
57462
|
+
function messageEligibleHelpAdvertisesOfflineReplay(helpText) {
|
|
57463
|
+
if (typeof helpText !== "string" || helpText.length === 0) {
|
|
57464
|
+
return false;
|
|
57465
|
+
}
|
|
57466
|
+
return helpText.toLowerCase().includes(MESSAGE_ELIGIBLE_OFFLINE_REPLAY_HELP_TOKEN);
|
|
57467
|
+
}
|
|
57468
|
+
function buildMessageEligibleArgs(params, opts) {
|
|
57469
|
+
const args = [
|
|
57470
|
+
"agent",
|
|
57471
|
+
"message-eligible",
|
|
57472
|
+
"--agent-id",
|
|
57473
|
+
params.agentId,
|
|
57474
|
+
"--client-agent-id",
|
|
57475
|
+
params.clientAgentId,
|
|
57476
|
+
"--provider-agent-id",
|
|
57477
|
+
params.providerAgentId,
|
|
57478
|
+
"--client-communication-address",
|
|
57479
|
+
params.clientCommunicationAddress,
|
|
57480
|
+
"--provider-communication-address",
|
|
57481
|
+
params.providerCommunicationAddress,
|
|
57482
|
+
"--job-id",
|
|
57483
|
+
params.jobId,
|
|
57484
|
+
"--group-id",
|
|
57485
|
+
params.groupId,
|
|
57486
|
+
"--direction",
|
|
57487
|
+
params.direction,
|
|
57488
|
+
"--provider-security-rate",
|
|
57489
|
+
String(params.providerSecurityRate)
|
|
57490
|
+
];
|
|
57491
|
+
if (opts.offlineReplaySupported) {
|
|
57492
|
+
args.push(MESSAGE_ELIGIBLE_OFFLINE_REPLAY_FLAG, String(params.isOfflineReplay));
|
|
57493
|
+
}
|
|
57494
|
+
return args;
|
|
57495
|
+
}
|
|
57496
|
+
function resolveOfflineReplayCapabilityMarker(supported) {
|
|
57497
|
+
return supported ? "supported" : "legacy_downgrade";
|
|
57498
|
+
}
|
|
57499
|
+
var capabilityProbe = null;
|
|
57500
|
+
var recommendedPairs = /* @__PURE__ */ new Set();
|
|
57501
|
+
function resetMessageEligibleOfflineReplayCapabilityForTests() {
|
|
57502
|
+
capabilityProbe = null;
|
|
57503
|
+
recommendedPairs.clear();
|
|
57504
|
+
}
|
|
57505
|
+
function maybeRecommendOnchainosUpgrade(supported) {
|
|
57506
|
+
if (supported || recommendedPairs.has(UPGRADE_RECOMMENDATION_PAIR_KEY)) {
|
|
57507
|
+
return;
|
|
57508
|
+
}
|
|
57509
|
+
const hook = XmtpService.getInstance().tools.notifyUpgradeRecommendation;
|
|
57510
|
+
if (!hook) {
|
|
57511
|
+
logWithTimestamp(
|
|
57512
|
+
"[onchainos] tools.notifyUpgradeRecommendation not injected \u2014 deferring offline-replay upgrade notice"
|
|
57513
|
+
);
|
|
57514
|
+
return;
|
|
57515
|
+
}
|
|
57516
|
+
recommendedPairs.add(UPGRADE_RECOMMENDATION_PAIR_KEY);
|
|
57517
|
+
try {
|
|
57518
|
+
void Promise.resolve(
|
|
57519
|
+
hook({
|
|
57520
|
+
component: "onchainos",
|
|
57521
|
+
capability: MESSAGE_ELIGIBLE_OFFLINE_REPLAY_HELP_TOKEN,
|
|
57522
|
+
reason: UPGRADE_RECOMMENDATION_REASON
|
|
57523
|
+
})
|
|
57524
|
+
).catch((err) => {
|
|
57525
|
+
logWithTimestamp("[onchainos] tools.notifyUpgradeRecommendation async delivery failed:", err);
|
|
57526
|
+
});
|
|
57527
|
+
} catch (err) {
|
|
57528
|
+
logWithTimestamp("[onchainos] tools.notifyUpgradeRecommendation threw:", err);
|
|
57529
|
+
}
|
|
57530
|
+
}
|
|
57531
|
+
function detectMessageEligibleOfflineReplaySupport(execFn = exec) {
|
|
57532
|
+
if (!capabilityProbe) {
|
|
57533
|
+
capabilityProbe = (async () => {
|
|
57534
|
+
try {
|
|
57535
|
+
const { stdout, stderr } = await execFn(["agent", "message-eligible", "--help"]);
|
|
57536
|
+
const supported = messageEligibleHelpAdvertisesOfflineReplay(`${stdout}
|
|
57537
|
+
${stderr}`);
|
|
57538
|
+
logWithTimestamp(
|
|
57539
|
+
`[onchainos] message-eligible offline-replay capability: ${supported ? "supported" : "legacy_downgrade"}`
|
|
57540
|
+
);
|
|
57541
|
+
return supported;
|
|
57542
|
+
} catch (err) {
|
|
57543
|
+
logWithTimestamp(
|
|
57544
|
+
"[onchainos] message-eligible --help probe failed; treating offline-replay as unsupported (legacy):",
|
|
57545
|
+
err
|
|
57546
|
+
);
|
|
57547
|
+
return false;
|
|
57548
|
+
}
|
|
57549
|
+
})().then((supported) => {
|
|
57550
|
+
maybeRecommendOnchainosUpgrade(supported);
|
|
57551
|
+
return supported;
|
|
57552
|
+
});
|
|
57553
|
+
}
|
|
57554
|
+
return capabilityProbe;
|
|
57555
|
+
}
|
|
57556
|
+
|
|
56811
57557
|
// ../core/src/xmtp-sdk/onchainos/system-config.ts
|
|
56812
57558
|
init_log();
|
|
56813
57559
|
init_sentry_logger();
|
|
@@ -57204,35 +57950,32 @@ async function sendHeartbeat(chainIndex) {
|
|
|
57204
57950
|
}
|
|
57205
57951
|
async function checkMessageEligible(params) {
|
|
57206
57952
|
logWithTimestamp(
|
|
57207
|
-
`[onchainos] checking message-eligible: job=${params.jobId} direction=${params.direction} providerSecurityRate=${params.providerSecurityRate}`
|
|
57953
|
+
`[onchainos] checking message-eligible: job=${params.jobId} direction=${params.direction} providerSecurityRate=${params.providerSecurityRate} isOfflineReplay=${params.isOfflineReplay}`
|
|
57208
57954
|
);
|
|
57955
|
+
const offlineReplaySupported = await detectMessageEligibleOfflineReplaySupport();
|
|
57956
|
+
const offlineReplayCapability = resolveOfflineReplayCapabilityMarker(offlineReplaySupported);
|
|
57957
|
+
const emitEligibilityChecked = (outcome, eligible) => {
|
|
57958
|
+
logger.info(LogEvent.MESSAGE_ELIGIBILITY_CHECKED, {
|
|
57959
|
+
component: "onchainos_cli",
|
|
57960
|
+
source: "onchainos",
|
|
57961
|
+
stage: "eligibility_check",
|
|
57962
|
+
direction: params.direction,
|
|
57963
|
+
jobId: params.jobId,
|
|
57964
|
+
isOfflineReplay: String(params.isOfflineReplay),
|
|
57965
|
+
offlineReplayCapability,
|
|
57966
|
+
outcome,
|
|
57967
|
+
eligible
|
|
57968
|
+
});
|
|
57969
|
+
};
|
|
57209
57970
|
let stdout;
|
|
57210
57971
|
let stderr;
|
|
57211
57972
|
try {
|
|
57212
|
-
({ stdout, stderr } = await exec(
|
|
57213
|
-
|
|
57214
|
-
|
|
57215
|
-
"--agent-id",
|
|
57216
|
-
params.agentId,
|
|
57217
|
-
"--client-agent-id",
|
|
57218
|
-
params.clientAgentId,
|
|
57219
|
-
"--provider-agent-id",
|
|
57220
|
-
params.providerAgentId,
|
|
57221
|
-
"--client-communication-address",
|
|
57222
|
-
params.clientCommunicationAddress,
|
|
57223
|
-
"--provider-communication-address",
|
|
57224
|
-
params.providerCommunicationAddress,
|
|
57225
|
-
"--job-id",
|
|
57226
|
-
params.jobId,
|
|
57227
|
-
"--group-id",
|
|
57228
|
-
params.groupId,
|
|
57229
|
-
"--direction",
|
|
57230
|
-
params.direction,
|
|
57231
|
-
"--provider-security-rate",
|
|
57232
|
-
String(params.providerSecurityRate)
|
|
57233
|
-
]));
|
|
57973
|
+
({ stdout, stderr } = await exec(
|
|
57974
|
+
buildMessageEligibleArgs(params, { offlineReplaySupported })
|
|
57975
|
+
));
|
|
57234
57976
|
} catch (err) {
|
|
57235
57977
|
guardCatchSessionExpired2(err, "message-eligible");
|
|
57978
|
+
emitEligibilityChecked("failed", "unknown");
|
|
57236
57979
|
throw messageEligibleUnavailableError({
|
|
57237
57980
|
reason: "message-eligible-cli-error",
|
|
57238
57981
|
stdout: typeof err?.stdout === "string" ? err.stdout : "",
|
|
@@ -57257,6 +58000,7 @@ async function checkMessageEligible(params) {
|
|
|
57257
58000
|
providerSecurityRate: String(params.providerSecurityRate)
|
|
57258
58001
|
});
|
|
57259
58002
|
} catch (err) {
|
|
58003
|
+
emitEligibilityChecked("failed", "unknown");
|
|
57260
58004
|
throw messageEligibleUnavailableError({
|
|
57261
58005
|
reason: "message-eligible-json-parse-failed",
|
|
57262
58006
|
stdout,
|
|
@@ -57286,6 +58030,7 @@ async function checkMessageEligible(params) {
|
|
|
57286
58030
|
reason: "ok=false"
|
|
57287
58031
|
})
|
|
57288
58032
|
);
|
|
58033
|
+
emitEligibilityChecked("failed", "unknown");
|
|
57289
58034
|
throw messageEligibleUnavailableError({
|
|
57290
58035
|
reason: "message-eligible-ok-false",
|
|
57291
58036
|
stdout,
|
|
@@ -57295,6 +58040,7 @@ async function checkMessageEligible(params) {
|
|
|
57295
58040
|
logWithTimestamp(
|
|
57296
58041
|
`[onchainos] message-eligible result: eligible=${res.data.eligible}`
|
|
57297
58042
|
);
|
|
58043
|
+
emitEligibilityChecked("success", String(res.data.eligible));
|
|
57298
58044
|
return res.data;
|
|
57299
58045
|
}
|
|
57300
58046
|
async function fetchSensitiveWords() {
|
|
@@ -58117,7 +58863,7 @@ function buildConnectParams(config, instanceId, protocolVersion) {
|
|
|
58117
58863
|
client: {
|
|
58118
58864
|
id: "gateway-client",
|
|
58119
58865
|
displayName: "okx-a2a-node",
|
|
58120
|
-
version: "0.2.
|
|
58866
|
+
version: "0.2.1-beta-8ae7a0d300-260807181806",
|
|
58121
58867
|
platform: "node",
|
|
58122
58868
|
mode: "backend",
|
|
58123
58869
|
instanceId
|
|
@@ -58128,7 +58874,7 @@ function buildConnectParams(config, instanceId, protocolVersion) {
|
|
|
58128
58874
|
commands: [],
|
|
58129
58875
|
permissions: {},
|
|
58130
58876
|
locale: Intl.DateTimeFormat().resolvedOptions().locale || "en-US",
|
|
58131
|
-
userAgent: `okx-a2a-node/${"0.2.
|
|
58877
|
+
userAgent: `okx-a2a-node/${"0.2.1-beta-8ae7a0d300-260807181806"}`,
|
|
58132
58878
|
auth: {
|
|
58133
58879
|
...config.token ? { token: config.token } : {},
|
|
58134
58880
|
...config.password ? { password: config.password } : {}
|
|
@@ -59890,7 +60636,9 @@ async function assertOutboundEligible(params) {
|
|
|
59890
60636
|
jobId,
|
|
59891
60637
|
groupId,
|
|
59892
60638
|
direction: isSenderClient ? "client_to_provider" : "provider_to_client",
|
|
59893
|
-
providerSecurityRate
|
|
60639
|
+
providerSecurityRate,
|
|
60640
|
+
// Outbound messages are never startup backlog recovery.
|
|
60641
|
+
isOfflineReplay: false
|
|
59894
60642
|
});
|
|
59895
60643
|
logWithTimestamp(
|
|
59896
60644
|
`[okx-agent-task] outbound message-eligible: senderAgentId=${senderAgent.agentId} receiverAgentId=${receiverAgent.agentId} job=${jobId} group=${groupId} result=${JSON.stringify(result)}`
|
|
@@ -62729,6 +63477,7 @@ async function verifyInboundA2AGroupMessage(params) {
|
|
|
62729
63477
|
messageId,
|
|
62730
63478
|
consentState,
|
|
62731
63479
|
trustedSystemSender = false,
|
|
63480
|
+
isOfflineReplay = false,
|
|
62732
63481
|
timing
|
|
62733
63482
|
} = params;
|
|
62734
63483
|
if (!isA2AEnvelope(payload)) {
|
|
@@ -62832,7 +63581,8 @@ async function verifyInboundA2AGroupMessage(params) {
|
|
|
62832
63581
|
jobId,
|
|
62833
63582
|
groupId,
|
|
62834
63583
|
direction: isSenderClient ? "client_to_provider" : "provider_to_client",
|
|
62835
|
-
providerSecurityRate
|
|
63584
|
+
providerSecurityRate,
|
|
63585
|
+
isOfflineReplay
|
|
62836
63586
|
});
|
|
62837
63587
|
timing?.mark("eligibilityCheck", eligibilityStartedAt);
|
|
62838
63588
|
logWithTimestamp(
|
|
@@ -63281,6 +64031,7 @@ async function processFileMessage(ctx, deps, options = {}) {
|
|
|
63281
64031
|
messageId,
|
|
63282
64032
|
consentState: ctx.conversation instanceof Group ? ctx.conversation.consentState() : void 0,
|
|
63283
64033
|
trustedSystemSender,
|
|
64034
|
+
isOfflineReplay: options.isOfflineReplay ?? false,
|
|
63284
64035
|
timing
|
|
63285
64036
|
});
|
|
63286
64037
|
if (!accepted) {
|
|
@@ -63864,6 +64615,7 @@ var DEFAULT_OFFLINE_REPLAY_INTERVAL_SEC = 300;
|
|
|
63864
64615
|
var DEFAULT_XMTP_CLIENT_RECYCLE_INTERVAL_SEC = 6 * 60 * 60;
|
|
63865
64616
|
var XMTP_CLIENT_RECYCLE_INTERVAL_ENV = "OKX_A2A_XMTP_CLIENT_RECYCLE_INTERVAL_SEC";
|
|
63866
64617
|
var HEARTBEAT_GATEWAY_CHECK_TIMEOUT_MS = 2e3;
|
|
64618
|
+
var UPGRADE_RECOMMENDATION_IDEMPOTENCY_KEY = "system:onchainos-offline-replay-upgrade";
|
|
63867
64619
|
function resolveOfflineReplayIntervalSec(systemConfig) {
|
|
63868
64620
|
const interval = systemConfig.offlineReplayInterval;
|
|
63869
64621
|
if (typeof interval !== "number" || !Number.isFinite(interval) || interval <= 0) {
|
|
@@ -64104,14 +64856,28 @@ async function runListenerWithLock(options, paths) {
|
|
|
64104
64856
|
reason: "append_backup_failed"
|
|
64105
64857
|
});
|
|
64106
64858
|
});
|
|
64859
|
+
},
|
|
64860
|
+
notifyUpgradeRecommendation: (input) => {
|
|
64861
|
+
const content = "The installed OnchainOS version does not support offline-replay preferences. Subscription messages will continue to replay normally. Upgrade OnchainOS to enable this capability.\n\nSuggested command: onchainos upgrade";
|
|
64862
|
+
void notifySystemMessageToUser({
|
|
64863
|
+
title: "OnchainOS upgrade recommended",
|
|
64864
|
+
content,
|
|
64865
|
+
store: sessionStore,
|
|
64866
|
+
idempotencyKey: UPGRADE_RECOMMENDATION_IDEMPOTENCY_KEY
|
|
64867
|
+
}).catch((err) => {
|
|
64868
|
+
logWithTimestamp(
|
|
64869
|
+
`[okx-agent-task] upgrade recommendation notify failed component=${input.component} capability=${input.capability}:`,
|
|
64870
|
+
err
|
|
64871
|
+
);
|
|
64872
|
+
});
|
|
64107
64873
|
}
|
|
64108
64874
|
});
|
|
64109
|
-
service.setPluginVersion("0.2.
|
|
64875
|
+
service.setPluginVersion("0.2.1-beta-8ae7a0d300-260807181806");
|
|
64110
64876
|
await service.init();
|
|
64111
64877
|
const pluginVersionStatus = service.pluginVersionStatus;
|
|
64112
64878
|
if (pluginVersionStatus.unavailable) {
|
|
64113
64879
|
throw new Error(
|
|
64114
|
-
`@okxweb3/a2a-node v${"0.2.
|
|
64880
|
+
`@okxweb3/a2a-node v${"0.2.1-beta-8ae7a0d300-260807181806"} is below the required minimum v${pluginVersionStatus.minVersion}`
|
|
64115
64881
|
);
|
|
64116
64882
|
}
|
|
64117
64883
|
const systemConfig = service.getSystemConfig();
|
|
@@ -64129,12 +64895,14 @@ async function runListenerWithLock(options, paths) {
|
|
|
64129
64895
|
onchainosAgentId: "*",
|
|
64130
64896
|
reason: "system-config missing sentryDsn",
|
|
64131
64897
|
pluginId: "@okxweb3/a2a-node",
|
|
64132
|
-
pluginVersion: "0.2.
|
|
64898
|
+
pluginVersion: "0.2.1-beta-8ae7a0d300-260807181806"
|
|
64133
64899
|
});
|
|
64134
64900
|
}
|
|
64135
64901
|
logWithTimestamp(
|
|
64136
64902
|
`[okx-agent-task] listener initialized, clients=${service.getClients().size}, home=${store.homeDir}`
|
|
64137
64903
|
);
|
|
64904
|
+
void detectMessageEligibleOfflineReplaySupport().catch(() => {
|
|
64905
|
+
});
|
|
64138
64906
|
const startupReplaySummary = await service.completeStartupReplay();
|
|
64139
64907
|
logWithTimestamp(
|
|
64140
64908
|
`[okx-agent-task] startup replay complete clients=${startupReplaySummary.clients} replayed=${startupReplaySummary.replayed} skipped=${startupReplaySummary.skipped} duration=${startupReplaySummary.durationMs}ms`
|
|
@@ -64272,7 +65040,7 @@ async function runListenerWithLock(options, paths) {
|
|
|
64272
65040
|
);
|
|
64273
65041
|
return;
|
|
64274
65042
|
}
|
|
64275
|
-
const replayResult = await timeSettled(() => service.replayOfflineMessages());
|
|
65043
|
+
const replayResult = await timeSettled(() => service.replayOfflineMessages("periodic_repair"));
|
|
64276
65044
|
const replayMs = replayResult.durationMs;
|
|
64277
65045
|
if (replayResult.error) {
|
|
64278
65046
|
logger.error(LogEvent.OFFLINE_REPLAY_FAILED, replayResult.error instanceof Error ? replayResult.error : new Error(String(replayResult.error)), {
|
|
@@ -64949,6 +65717,7 @@ function summarizeXmtpTestEvents(runId, events) {
|
|
|
64949
65717
|
const nodeDurations = /* @__PURE__ */ new Map();
|
|
64950
65718
|
const replayLags = /* @__PURE__ */ new Map();
|
|
64951
65719
|
const replayHandles = /* @__PURE__ */ new Map();
|
|
65720
|
+
const streamRecoveries = /* @__PURE__ */ new Map();
|
|
64952
65721
|
const agentMap = /* @__PURE__ */ new Map();
|
|
64953
65722
|
for (const event of events) {
|
|
64954
65723
|
const key = deliveryKey(event);
|
|
@@ -64981,6 +65750,18 @@ function summarizeXmtpTestEvents(runId, events) {
|
|
|
64981
65750
|
event.handlerTotalMs
|
|
64982
65751
|
);
|
|
64983
65752
|
}
|
|
65753
|
+
if (event.eventName === "Agent stream recovered") {
|
|
65754
|
+
setDuration(
|
|
65755
|
+
streamRecoveries,
|
|
65756
|
+
[
|
|
65757
|
+
eventAgentId(event),
|
|
65758
|
+
stringValue(event.clientGeneration) || "unknown-client",
|
|
65759
|
+
stringValue(event.recoverySequence) || "unknown-recovery",
|
|
65760
|
+
event.timestamp
|
|
65761
|
+
].join(":"),
|
|
65762
|
+
event.recoveryDurationMs
|
|
65763
|
+
);
|
|
65764
|
+
}
|
|
64984
65765
|
}
|
|
64985
65766
|
const agents = [...agentMap.entries()].filter(([, value]) => value.live.size > 0 || value.replay.size > 0).map(([agentId, value]) => {
|
|
64986
65767
|
const total = (/* @__PURE__ */ new Set([...value.live, ...value.replay])).size;
|
|
@@ -65002,7 +65783,9 @@ function summarizeXmtpTestEvents(runId, events) {
|
|
|
65002
65783
|
duplicateEvents: countEvent(events, "Inbound ignored: duplicate message"),
|
|
65003
65784
|
replayMessageFailures: countEvent(events, "Offline replay message failed"),
|
|
65004
65785
|
replayScanFailures: countEvent(events, "Offline replay failed"),
|
|
65005
|
-
streamFailures: countEvent(events, "conversations.stream failed") + countEvent(events, "
|
|
65786
|
+
streamFailures: countEvent(events, "conversations.stream failed") + countEvent(events, "agent stream error"),
|
|
65787
|
+
streamRecoveries: countEvent(events, "Agent stream recovered"),
|
|
65788
|
+
streamRecoveryTimeouts: countEvent(events, "Agent stream recovery timeout"),
|
|
65006
65789
|
connectionFailures: countEvent(events, "XMTP connection failed"),
|
|
65007
65790
|
successfulReplayScans: countEvent(events, "Address sync completed"),
|
|
65008
65791
|
replayScansWithMessages: events.filter((event) => event.eventName === "Address sync completed" && numericValue(event.replayed) > 0).length,
|
|
@@ -65010,6 +65793,7 @@ function summarizeXmtpTestEvents(runId, events) {
|
|
|
65010
65793
|
nodeHandlerMs: summarizeDurations([...nodeDurations.values()]),
|
|
65011
65794
|
replayLagMs: summarizeDurations([...replayLags.values()]),
|
|
65012
65795
|
replayHandleMs: summarizeDurations([...replayHandles.values()]),
|
|
65796
|
+
streamRecoveryMs: summarizeDurations([...streamRecoveries.values()]),
|
|
65013
65797
|
agents
|
|
65014
65798
|
};
|
|
65015
65799
|
}
|
|
@@ -65024,6 +65808,8 @@ Reliability
|
|
|
65024
65808
|
Replay message failures ${summary.replayMessageFailures}
|
|
65025
65809
|
Replay scan failures ${summary.replayScanFailures}
|
|
65026
65810
|
Stream failures ${summary.streamFailures}
|
|
65811
|
+
Stream recoveries ${summary.streamRecoveries}
|
|
65812
|
+
Recovery timeouts (>30s) ${summary.streamRecoveryTimeouts}
|
|
65027
65813
|
XMTP connection failures ${summary.connectionFailures}
|
|
65028
65814
|
Replay scans ${summary.successfulReplayScans}
|
|
65029
65815
|
Scans with replay ${summary.replayScansWithMessages}
|
|
@@ -65032,7 +65818,8 @@ Timing
|
|
|
65032
65818
|
XMTP delivery p50/p95/max ${formatDurationSummary(summary.xmtpDeliveryMs)}
|
|
65033
65819
|
Node handler p50/p95/max ${formatDurationSummary(summary.nodeHandlerMs)}
|
|
65034
65820
|
Replay lag p50/p95/max ${formatDurationSummary(summary.replayLagMs)}
|
|
65035
|
-
Replay handler p50/p95/max ${formatDurationSummary(summary.replayHandleMs)}
|
|
65821
|
+
Replay handler p50/p95/max ${formatDurationSummary(summary.replayHandleMs)}
|
|
65822
|
+
Stream recovery p50/p95/max ${formatDurationSummary(summary.streamRecoveryMs)}`);
|
|
65036
65823
|
if (summary.agents.length > 0) {
|
|
65037
65824
|
console.log("\nAgents");
|
|
65038
65825
|
for (const agent of summary.agents) {
|
|
@@ -65378,6 +66165,36 @@ init_ai_command();
|
|
|
65378
66165
|
init_update_cli();
|
|
65379
66166
|
init_win_spawn();
|
|
65380
66167
|
|
|
66168
|
+
// src/capabilities-cli.ts
|
|
66169
|
+
function getA2ACapabilities() {
|
|
66170
|
+
return {
|
|
66171
|
+
messageEligibleOfflineReplay: {
|
|
66172
|
+
ok: true,
|
|
66173
|
+
fixCommands: [],
|
|
66174
|
+
message: ""
|
|
66175
|
+
}
|
|
66176
|
+
};
|
|
66177
|
+
}
|
|
66178
|
+
var CAPABILITIES_USAGE = "Usage: okx-a2a capabilities [--json]\n\nPrint this package's machine-readable A2A capability negotiation status.\nOnchainOS runs `okx-a2a capabilities --json` to detect supported capabilities.\n";
|
|
66179
|
+
function handleCapabilitiesCommand(args) {
|
|
66180
|
+
if (args.some((arg) => arg === "-h" || arg === "--help")) {
|
|
66181
|
+
process.stdout.write(CAPABILITIES_USAGE);
|
|
66182
|
+
return;
|
|
66183
|
+
}
|
|
66184
|
+
const unknown = args.filter((arg) => arg !== "--json");
|
|
66185
|
+
if (unknown.length > 0) {
|
|
66186
|
+
throw new Error(`Unknown capabilities option: ${unknown[0]}`);
|
|
66187
|
+
}
|
|
66188
|
+
const capabilities = getA2ACapabilities();
|
|
66189
|
+
if (args.includes("--json")) {
|
|
66190
|
+
process.stdout.write(`${JSON.stringify(capabilities)}
|
|
66191
|
+
`);
|
|
66192
|
+
return;
|
|
66193
|
+
}
|
|
66194
|
+
process.stdout.write(`${JSON.stringify(capabilities, null, 2)}
|
|
66195
|
+
`);
|
|
66196
|
+
}
|
|
66197
|
+
|
|
65381
66198
|
// src/logs-export.ts
|
|
65382
66199
|
var import_node_child_process10 = require("node:child_process");
|
|
65383
66200
|
var import_node_fs27 = require("node:fs");
|
|
@@ -66698,7 +67515,7 @@ async function exportDiagnosticLogs(options) {
|
|
|
66698
67515
|
node: process.version,
|
|
66699
67516
|
platform: process.platform,
|
|
66700
67517
|
arch: process.arch,
|
|
66701
|
-
packageVersion: true ? "0.2.
|
|
67518
|
+
packageVersion: true ? "0.2.1-beta-8ae7a0d300-260807181806" : "unknown",
|
|
66702
67519
|
sensitiveContentIncluded: options.includeSensitiveContent,
|
|
66703
67520
|
listenerAndLlmContentIncluded: true,
|
|
66704
67521
|
credentialsAlwaysRedacted: true,
|
|
@@ -68423,7 +69240,7 @@ async function runDoctor(options = {}) {
|
|
|
68423
69240
|
platform: options.platform ?? process.platform,
|
|
68424
69241
|
env: options.env ?? process.env,
|
|
68425
69242
|
target: options.target ?? resolveDoctorTarget(options.env ?? process.env),
|
|
68426
|
-
cliVersion: options.cliVersion ?? (true ? "0.2.
|
|
69243
|
+
cliVersion: options.cliVersion ?? (true ? "0.2.1-beta-8ae7a0d300-260807181806" : "0.0.0"),
|
|
68427
69244
|
fixMode: options.fix === true,
|
|
68428
69245
|
nonInteractive: options.nonInteractive === true,
|
|
68429
69246
|
packageChanged: false,
|
|
@@ -68657,6 +69474,8 @@ init_autostart_windows();
|
|
|
68657
69474
|
HEARTBEAT_GATEWAY_CHECK_TIMEOUT_MS,
|
|
68658
69475
|
InboundReplayGate,
|
|
68659
69476
|
InvalidXmtpMessageStore,
|
|
69477
|
+
MESSAGE_ELIGIBLE_OFFLINE_REPLAY_FLAG,
|
|
69478
|
+
MESSAGE_ELIGIBLE_OFFLINE_REPLAY_HELP_TOKEN,
|
|
68660
69479
|
NATIVE_LAUNCHER_EXE_NAME,
|
|
68661
69480
|
OPENCLAW_GATEWAY_ROUTE_GROUP_ID,
|
|
68662
69481
|
SYSTEM_NOTIFICATION_SESSION_KEY,
|
|
@@ -68674,6 +69493,7 @@ init_autostart_windows();
|
|
|
68674
69493
|
XMTP_CLIENT_RECYCLE_INTERVAL_ENV,
|
|
68675
69494
|
XmtpDm,
|
|
68676
69495
|
XmtpGroup,
|
|
69496
|
+
XmtpService,
|
|
68677
69497
|
acquireDaemonLock,
|
|
68678
69498
|
activeDaemonPointerPath,
|
|
68679
69499
|
aiRunSentryExtra,
|
|
@@ -68694,6 +69514,7 @@ init_autostart_windows();
|
|
|
68694
69514
|
buildInboundTerminalExtras,
|
|
68695
69515
|
buildLaunchdPlist,
|
|
68696
69516
|
buildLauncherEntryJs,
|
|
69517
|
+
buildMessageEligibleArgs,
|
|
68697
69518
|
buildPendingConversationBackupDispatch,
|
|
68698
69519
|
buildSchtasksCreateArgs,
|
|
68699
69520
|
buildSchtasksDeleteArgs,
|
|
@@ -68725,6 +69546,7 @@ init_autostart_windows();
|
|
|
68725
69546
|
detectAiProviders,
|
|
68726
69547
|
detectCurrentAiProvider,
|
|
68727
69548
|
detectGatewayInvocation,
|
|
69549
|
+
detectMessageEligibleOfflineReplaySupport,
|
|
68728
69550
|
detectRuntime,
|
|
68729
69551
|
ensureDaemonReady,
|
|
68730
69552
|
ensureDefaultAiProvider,
|
|
@@ -68738,9 +69560,11 @@ init_autostart_windows();
|
|
|
68738
69560
|
findWindowsNativeOkxA2aExe,
|
|
68739
69561
|
followFile,
|
|
68740
69562
|
formatDoctorReportForHumans,
|
|
69563
|
+
getA2ACapabilities,
|
|
68741
69564
|
getDaemonStatus,
|
|
68742
69565
|
getHermesGatewayPluginStatus,
|
|
68743
69566
|
getSessionBusyTracker,
|
|
69567
|
+
handleCapabilitiesCommand,
|
|
68744
69568
|
handleDoctorCommand,
|
|
68745
69569
|
handleXmtpDebugCommand,
|
|
68746
69570
|
handleXmtpSendCommand,
|
|
@@ -68754,6 +69578,7 @@ init_autostart_windows();
|
|
|
68754
69578
|
isDefaultTaskHome,
|
|
68755
69579
|
isGatewayAvailableForHeartbeat,
|
|
68756
69580
|
isHermesGatewayPluginEnabled,
|
|
69581
|
+
isOfflineReplayForTrigger,
|
|
68757
69582
|
isOpenClawA2aPluginAvailable,
|
|
68758
69583
|
isOpenClawGatewayAvailable,
|
|
68759
69584
|
isOriginalParentProcessAlive,
|
|
@@ -68765,6 +69590,8 @@ init_autostart_windows();
|
|
|
68765
69590
|
launchdPlistHasCurrentRestartPolicy,
|
|
68766
69591
|
logWinCompat,
|
|
68767
69592
|
logXmtpMessageSent,
|
|
69593
|
+
maybeRecommendOnchainosUpgrade,
|
|
69594
|
+
messageEligibleHelpAdvertisesOfflineReplay,
|
|
68768
69595
|
nodeVersionSatisfies,
|
|
68769
69596
|
normalizeAiProvider,
|
|
68770
69597
|
normalizeHermesOkxA2aPluginConfig,
|
|
@@ -68790,6 +69617,7 @@ init_autostart_windows();
|
|
|
68790
69617
|
removeUserAttentionWatcher,
|
|
68791
69618
|
reportDoctorRunToSentry,
|
|
68792
69619
|
reportUserNotificationFailure,
|
|
69620
|
+
resetMessageEligibleOfflineReplayCapabilityForTests,
|
|
68793
69621
|
resetResolvedOnchainosBinForTests,
|
|
68794
69622
|
resolveAiPermissionPreset,
|
|
68795
69623
|
resolveAiProviderCommand,
|
|
@@ -68801,6 +69629,7 @@ init_autostart_windows();
|
|
|
68801
69629
|
resolveDoctorTarget,
|
|
68802
69630
|
resolveEnvelopePayload,
|
|
68803
69631
|
resolveNpmCmdShimScript,
|
|
69632
|
+
resolveOfflineReplayCapabilityMarker,
|
|
68804
69633
|
resolveOfflineReplayIntervalSec,
|
|
68805
69634
|
resolveOpenClawGatewayConfig,
|
|
68806
69635
|
resolveOpenClawGatewayRoute,
|