@okxweb3/a2a-node 0.2.17 → 0.2.18-beta-4dd056b897-261015113839
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 +1682 -124
- package/dist/index.js +1585 -127
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -4008,7 +4008,7 @@ var require_is = __commonJS({
|
|
|
4008
4008
|
function isPrimitive(wat) {
|
|
4009
4009
|
return wat === null || typeof wat !== "object" && typeof wat !== "function";
|
|
4010
4010
|
}
|
|
4011
|
-
function
|
|
4011
|
+
function isPlainObject6(wat) {
|
|
4012
4012
|
return isBuiltin(wat, "Object");
|
|
4013
4013
|
}
|
|
4014
4014
|
function isEvent(wat) {
|
|
@@ -4024,7 +4024,7 @@ var require_is = __commonJS({
|
|
|
4024
4024
|
return Boolean(wat && wat.then && typeof wat.then === "function");
|
|
4025
4025
|
}
|
|
4026
4026
|
function isSyntheticEvent(wat) {
|
|
4027
|
-
return
|
|
4027
|
+
return isPlainObject6(wat) && "nativeEvent" in wat && "preventDefault" in wat && "stopPropagation" in wat;
|
|
4028
4028
|
}
|
|
4029
4029
|
function isNaN2(wat) {
|
|
4030
4030
|
return typeof wat === "number" && wat !== wat;
|
|
@@ -4047,7 +4047,7 @@ var require_is = __commonJS({
|
|
|
4047
4047
|
exports2.isEvent = isEvent;
|
|
4048
4048
|
exports2.isInstanceOf = isInstanceOf;
|
|
4049
4049
|
exports2.isNaN = isNaN2;
|
|
4050
|
-
exports2.isPlainObject =
|
|
4050
|
+
exports2.isPlainObject = isPlainObject6;
|
|
4051
4051
|
exports2.isPrimitive = isPrimitive;
|
|
4052
4052
|
exports2.isRegExp = isRegExp;
|
|
4053
4053
|
exports2.isString = isString;
|
|
@@ -19310,6 +19310,23 @@ var init_events = __esm({
|
|
|
19310
19310
|
XMTP_RATE_LIMIT_CREATE_SUPPRESSED: "XMTP rate limit create suppressed",
|
|
19311
19311
|
XMTP_RATE_LIMIT_PROBE: "XMTP rate limit probe",
|
|
19312
19312
|
XMTP_RATE_LIMIT_RECOVERED: "XMTP rate limit recovered",
|
|
19313
|
+
// ── subscription observability info (DEXMARKET-9096) ───────────
|
|
19314
|
+
// All of the following logger.info checkpoints MUST also be listed in
|
|
19315
|
+
// SENTRY_INFO_ALLOWLIST (index.ts): info() returns early for an unlisted
|
|
19316
|
+
// event, which ships a checkpoint that looks implemented but emits nothing.
|
|
19317
|
+
SUBSCRIPTION_PUSH_STARTED: "Subscription push started",
|
|
19318
|
+
SUBSCRIPTION_PUSH_TARGETS_RESOLVED: "Subscription push targets resolved",
|
|
19319
|
+
SUBSCRIPTION_PUSH_EMPTY_TARGETS: "Subscription push empty targets",
|
|
19320
|
+
SUBSCRIPTION_PUSH_SUMMARY: "Subscription push summary",
|
|
19321
|
+
SUBSCRIPTION_INBOUND_RECEIVED: "Subscription inbound received",
|
|
19322
|
+
SUBSCRIPTION_INBOUND_GATE_DROPPED: "Subscription inbound gate dropped",
|
|
19323
|
+
SUBSCRIPTION_JOBS_QUERY_STARTED: "Subscription jobs query started",
|
|
19324
|
+
SUBSCRIPTION_JOBS_QUERY_SUCCEEDED: "Subscription jobs query succeeded",
|
|
19325
|
+
SUBSCRIPTION_JOBS_EMPTY: "Subscription jobs empty",
|
|
19326
|
+
SUBSCRIPTION_INBOUND_OWNERSHIP_ROUTED: "Subscription inbound ownership routed",
|
|
19327
|
+
SUBSCRIPTION_JOB_DISPATCHED: "Subscription job dispatched",
|
|
19328
|
+
SUBSCRIPTION_JOB_DUPLICATE_IGNORED: "Subscription job duplicate ignored",
|
|
19329
|
+
SUBSCRIPTION_FANOUT_SUMMARY: "Subscription fan-out summary",
|
|
19313
19330
|
// ── error ─────────────────────────────────────────────────────
|
|
19314
19331
|
XMTP_CONNECTION_FAILED: "XMTP connection failed",
|
|
19315
19332
|
CONVERSATIONS_STREAM_FAILED: "conversations.stream failed",
|
|
@@ -19376,6 +19393,13 @@ var init_events = __esm({
|
|
|
19376
19393
|
AGENT_INSTALLATION_LIMIT_NEAR: "Agent installation limit near",
|
|
19377
19394
|
XMTP_HISTORY_SYNC_REQUEST_FAILED: "XMTP history sync request failed",
|
|
19378
19395
|
XMTP_DEBUG_SYNC_FAILED: "XMTP debug sync failed",
|
|
19396
|
+
// ── subscription observability error (DEXMARKET-9096) ──────────
|
|
19397
|
+
// error-level: always emitted (no allowlist gate). Error objects are
|
|
19398
|
+
// classified by buildErrorDiagnostics — never attach raw Error.message.
|
|
19399
|
+
SUBSCRIPTION_PUSH_TARGET_FAILED: "Subscription push target failed",
|
|
19400
|
+
SUBSCRIPTION_INBOUND_AGENTIC_ID_MISSING: "Subscription inbound agenticId missing",
|
|
19401
|
+
SUBSCRIPTION_JOBS_FAIL_CLOSED: "Subscription jobs fail closed",
|
|
19402
|
+
SUBSCRIPTION_JOB_FAILED: "Subscription job failed",
|
|
19379
19403
|
// Underlying XMTP SDK client close failed during recycle/removal/shutdown
|
|
19380
19404
|
// (DEXMARKET-9116). Error-level → NOT added to SENTRY_INFO_ALLOWLIST.
|
|
19381
19405
|
XMTP_CLIENT_CLOSE_FAILED: "XMTP client close failed"
|
|
@@ -19439,7 +19463,7 @@ function resolveDeliveryId(input) {
|
|
|
19439
19463
|
if (slots.every((slot) => slot === "")) {
|
|
19440
19464
|
return UNKNOWN_LOG_FIELD;
|
|
19441
19465
|
}
|
|
19442
|
-
const digest = (0,
|
|
19466
|
+
const digest = (0, import_node_crypto3.createHash)("sha256").update(slots.join("|")).digest("hex");
|
|
19443
19467
|
return `${DERIVED_DELIVERY_ID_PREFIX}${digest.slice(0, DERIVED_DELIVERY_ID_LENGTH)}`;
|
|
19444
19468
|
}
|
|
19445
19469
|
function releaseFields(release) {
|
|
@@ -19557,11 +19581,11 @@ function enrichCorrelationFields(extra) {
|
|
|
19557
19581
|
}
|
|
19558
19582
|
return enriched;
|
|
19559
19583
|
}
|
|
19560
|
-
var
|
|
19584
|
+
var import_node_crypto3, PROBE_NAME_PATTERN, PROBE_JOB_ID_PATTERN, XMTP_MESSAGE_ID_PATTERN, DERIVED_DELIVERY_ID_PREFIX, DERIVED_DELIVERY_ID_LENGTH, RELEASE_CODE_MAJOR_WEIGHT, RELEASE_CODE_MINOR_WEIGHT, UNKNOWN_LOG_FIELD, UNPARSABLE_RELEASE;
|
|
19561
19585
|
var init_log_fields = __esm({
|
|
19562
19586
|
"../core/src/sentry-logger/log-fields.ts"() {
|
|
19563
19587
|
"use strict";
|
|
19564
|
-
|
|
19588
|
+
import_node_crypto3 = require("node:crypto");
|
|
19565
19589
|
PROBE_NAME_PATTERN = /probe/i;
|
|
19566
19590
|
PROBE_JOB_ID_PATTERN = /^probe[-_]/i;
|
|
19567
19591
|
XMTP_MESSAGE_ID_PATTERN = /^[0-9a-f]{16,}$/i;
|
|
@@ -19949,6 +19973,9 @@ function applyFatalEventDefaults(event) {
|
|
|
19949
19973
|
function isInfoEventAllowlisted(name) {
|
|
19950
19974
|
return SENTRY_INFO_ALLOWLIST.has(name);
|
|
19951
19975
|
}
|
|
19976
|
+
function isFingerprintKey(key) {
|
|
19977
|
+
return SENTRY_FINGERPRINT_KEYS.includes(key);
|
|
19978
|
+
}
|
|
19952
19979
|
function isTagKey(key) {
|
|
19953
19980
|
return SENTRY_TAG_KEYS.has(key);
|
|
19954
19981
|
}
|
|
@@ -19960,13 +19987,13 @@ function agentExtras(identity) {
|
|
|
19960
19987
|
role: identity.role != null && identity.role !== "" ? String(identity.role) : UNKNOWN_FIELD
|
|
19961
19988
|
};
|
|
19962
19989
|
}
|
|
19963
|
-
var Sentry,
|
|
19990
|
+
var Sentry, import_node_crypto4, FLOW_ID, SENTRY_EXTRA_BLOCKLIST, SENTRY_EXTRA_BLOCKED_KEY_PARTS, SENTRY_FULL_STRING_EXTRA_KEYS, SENTRY_TAG_KEYS, SENTRY_FINGERPRINT_KEYS, SENTRY_INFO_ALLOWLIST, MAX_EXTRA_STRING_LENGTH, MAX_TAG_VALUE_LENGTH, RELEASE_FIELDS, RUNTIME_FIELDS, SentryLogger, logger, initLogger, shutdown, UNKNOWN_FIELD;
|
|
19964
19991
|
var init_sentry_logger = __esm({
|
|
19965
19992
|
"../core/src/sentry-logger/index.ts"() {
|
|
19966
19993
|
"use strict";
|
|
19967
19994
|
init_log();
|
|
19968
19995
|
Sentry = __toESM(require_cjs4());
|
|
19969
|
-
|
|
19996
|
+
import_node_crypto4 = require("node:crypto");
|
|
19970
19997
|
init_events();
|
|
19971
19998
|
init_log_fields();
|
|
19972
19999
|
init_xmtp_test_metrics();
|
|
@@ -19974,7 +20001,7 @@ var init_sentry_logger = __esm({
|
|
|
19974
20001
|
init_runtime_metadata();
|
|
19975
20002
|
init_events();
|
|
19976
20003
|
init_log_fields();
|
|
19977
|
-
FLOW_ID = (0,
|
|
20004
|
+
FLOW_ID = (0, import_node_crypto4.randomUUID)();
|
|
19978
20005
|
SENTRY_EXTRA_BLOCKLIST = /* @__PURE__ */ new Set([
|
|
19979
20006
|
"args",
|
|
19980
20007
|
"apikey",
|
|
@@ -20057,6 +20084,13 @@ var init_sentry_logger = __esm({
|
|
|
20057
20084
|
]);
|
|
20058
20085
|
SENTRY_TAG_KEYS = /* @__PURE__ */ new Set([
|
|
20059
20086
|
"agentId",
|
|
20087
|
+
// Subscription correlation agent ids (DEXMARKET-9096). Bounded-cardinality,
|
|
20088
|
+
// same class as agentId/senderAgentId/onchainosAgentId — promoted to indexed
|
|
20089
|
+
// tags for Sentry filtering. NOT added to SENTRY_FINGERPRINT_KEYS, so the
|
|
20090
|
+
// global issue fingerprint is unchanged. High-cardinality ids
|
|
20091
|
+
// (conversationId/messageId/deliveryId) are deliberately NOT here.
|
|
20092
|
+
"aspAgentId",
|
|
20093
|
+
"userAgentId",
|
|
20060
20094
|
"agentPlatform",
|
|
20061
20095
|
"aiProvider",
|
|
20062
20096
|
"cacheName",
|
|
@@ -20224,6 +20258,22 @@ var init_sentry_logger = __esm({
|
|
|
20224
20258
|
LogEvent.SESSION_KEY_DERIVED,
|
|
20225
20259
|
LogEvent.SESSIONS_QUERIED,
|
|
20226
20260
|
LogEvent.SYNC_TICK_COMPLETED,
|
|
20261
|
+
// Subscription observability info checkpoints (DEXMARKET-9096). Each is a
|
|
20262
|
+
// logger.info event; omitting any makes info() drop it silently so the whole
|
|
20263
|
+
// subscription trace would look implemented and emit nothing in production.
|
|
20264
|
+
LogEvent.SUBSCRIPTION_PUSH_STARTED,
|
|
20265
|
+
LogEvent.SUBSCRIPTION_PUSH_TARGETS_RESOLVED,
|
|
20266
|
+
LogEvent.SUBSCRIPTION_PUSH_EMPTY_TARGETS,
|
|
20267
|
+
LogEvent.SUBSCRIPTION_PUSH_SUMMARY,
|
|
20268
|
+
LogEvent.SUBSCRIPTION_INBOUND_RECEIVED,
|
|
20269
|
+
LogEvent.SUBSCRIPTION_INBOUND_GATE_DROPPED,
|
|
20270
|
+
LogEvent.SUBSCRIPTION_JOBS_QUERY_STARTED,
|
|
20271
|
+
LogEvent.SUBSCRIPTION_JOBS_QUERY_SUCCEEDED,
|
|
20272
|
+
LogEvent.SUBSCRIPTION_JOBS_EMPTY,
|
|
20273
|
+
LogEvent.SUBSCRIPTION_INBOUND_OWNERSHIP_ROUTED,
|
|
20274
|
+
LogEvent.SUBSCRIPTION_JOB_DISPATCHED,
|
|
20275
|
+
LogEvent.SUBSCRIPTION_JOB_DUPLICATE_IGNORED,
|
|
20276
|
+
LogEvent.SUBSCRIPTION_FANOUT_SUMMARY,
|
|
20227
20277
|
// XMTP creation rate-limit cooldown checkpoints (DEXMARKET-9116). info() drops
|
|
20228
20278
|
// any event not listed here, so these must stay registered.
|
|
20229
20279
|
LogEvent.XMTP_RATE_LIMIT_COOLDOWN_STARTED,
|
|
@@ -31015,7 +31065,7 @@ var require_websocket2 = __commonJS({
|
|
|
31015
31065
|
var http2 = require("http");
|
|
31016
31066
|
var net = require("net");
|
|
31017
31067
|
var tls = require("tls");
|
|
31018
|
-
var { randomBytes: randomBytes3, createHash:
|
|
31068
|
+
var { randomBytes: randomBytes3, createHash: createHash7 } = require("crypto");
|
|
31019
31069
|
var { Duplex, Readable } = require("stream");
|
|
31020
31070
|
var { URL: URL2 } = require("url");
|
|
31021
31071
|
var PerMessageDeflate = require_permessage_deflate();
|
|
@@ -31675,7 +31725,7 @@ var require_websocket2 = __commonJS({
|
|
|
31675
31725
|
abortHandshake(websocket, socket, "Invalid Upgrade header");
|
|
31676
31726
|
return;
|
|
31677
31727
|
}
|
|
31678
|
-
const digest =
|
|
31728
|
+
const digest = createHash7("sha1").update(key + GUID).digest("base64");
|
|
31679
31729
|
if (res.headers["sec-websocket-accept"] !== digest) {
|
|
31680
31730
|
abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
|
|
31681
31731
|
return;
|
|
@@ -32042,7 +32092,7 @@ var require_websocket_server = __commonJS({
|
|
|
32042
32092
|
var EventEmitter2 = require("events");
|
|
32043
32093
|
var http2 = require("http");
|
|
32044
32094
|
var { Duplex } = require("stream");
|
|
32045
|
-
var { createHash:
|
|
32095
|
+
var { createHash: createHash7 } = require("crypto");
|
|
32046
32096
|
var extension = require_extension();
|
|
32047
32097
|
var PerMessageDeflate = require_permessage_deflate();
|
|
32048
32098
|
var subprotocol = require_subprotocol();
|
|
@@ -32343,7 +32393,7 @@ var require_websocket_server = __commonJS({
|
|
|
32343
32393
|
);
|
|
32344
32394
|
}
|
|
32345
32395
|
if (this._state > RUNNING) return abortHandshake(socket, 503);
|
|
32346
|
-
const digest =
|
|
32396
|
+
const digest = createHash7("sha1").update(key + GUID).digest("base64");
|
|
32347
32397
|
const headers = [
|
|
32348
32398
|
"HTTP/1.1 101 Switching Protocols",
|
|
32349
32399
|
"Upgrade: websocket",
|
|
@@ -32465,7 +32515,7 @@ var init_sentry_config = __esm({
|
|
|
32465
32515
|
environment = process.env.SENTRY_ENV === "dev" ? "dev" : "prod";
|
|
32466
32516
|
SENTRY_CONFIG = {
|
|
32467
32517
|
projectName: "okx/openclaw-okx-a2a-extension",
|
|
32468
|
-
release: "0.2.
|
|
32518
|
+
release: "0.2.18-beta-4dd056b897-261015113839",
|
|
32469
32519
|
environment,
|
|
32470
32520
|
runtimeContainer: normalizeRuntimeContainer(process.env.OKX_A2A_RUNTIME_CONTAINER)
|
|
32471
32521
|
};
|
|
@@ -33421,7 +33471,7 @@ async function getCurrentNodeCliVersion() {
|
|
|
33421
33471
|
return await getGlobalNpmPackageVersion(UPDATE_PACKAGES.node) ?? getBundledNodeCliVersion();
|
|
33422
33472
|
}
|
|
33423
33473
|
function getBundledNodeCliVersion() {
|
|
33424
|
-
return true ? "0.2.
|
|
33474
|
+
return true ? "0.2.18-beta-4dd056b897-261015113839" : null;
|
|
33425
33475
|
}
|
|
33426
33476
|
function readConfiguredAiProvider() {
|
|
33427
33477
|
const explicit = process.env.OKX_A2A_AI_PROVIDER || process.env.OKX_AGENT_TASK_AI_CLI;
|
|
@@ -33631,7 +33681,7 @@ async function updateHermes(release, options) {
|
|
|
33631
33681
|
}
|
|
33632
33682
|
}
|
|
33633
33683
|
async function installGatewayPluginForDoctor(target) {
|
|
33634
|
-
const release = isPrereleaseVersion("0.2.
|
|
33684
|
+
const release = isPrereleaseVersion("0.2.18-beta-4dd056b897-261015113839") ? "beta" : "latest";
|
|
33635
33685
|
const insideTargetGateway = detectGatewayInvocation() === target;
|
|
33636
33686
|
const options = {
|
|
33637
33687
|
restart: !insideTargetGateway,
|
|
@@ -44353,6 +44403,7 @@ __export(index_exports, {
|
|
|
44353
44403
|
InboundReplayGate: () => InboundReplayGate,
|
|
44354
44404
|
InvalidXmtpMessageStore: () => InvalidXmtpMessageStore,
|
|
44355
44405
|
JOB_PROVIDER_BINDING_SOURCES: () => JOB_PROVIDER_BINDING_SOURCES,
|
|
44406
|
+
LIST_JOBS_BY_VERIFIED_SENDER_HELP_TOKEN: () => LIST_JOBS_BY_VERIFIED_SENDER_HELP_TOKEN,
|
|
44356
44407
|
ListenerDeferredTaskScheduler: () => ListenerDeferredTaskScheduler,
|
|
44357
44408
|
ListenerMaintenanceGate: () => ListenerMaintenanceGate,
|
|
44358
44409
|
LogEvent: () => LogEvent,
|
|
@@ -44362,6 +44413,9 @@ __export(index_exports, {
|
|
|
44362
44413
|
NATIVE_LAUNCHER_EXE_NAME: () => NATIVE_LAUNCHER_EXE_NAME,
|
|
44363
44414
|
OPENCLAW_GATEWAY_ROUTE_GROUP_ID: () => OPENCLAW_GATEWAY_ROUTE_GROUP_ID,
|
|
44364
44415
|
ProviderNotReadyError: () => ProviderNotReadyError,
|
|
44416
|
+
RUN_LOG_FILENAME_MAX_BYTES: () => RUN_LOG_FILENAME_MAX_BYTES,
|
|
44417
|
+
SUBSCRIPTION_FANOUT_MAX: () => SUBSCRIPTION_FANOUT_MAX,
|
|
44418
|
+
SUBSCRIPTION_MESSAGE_TYPE: () => SUBSCRIPTION_MESSAGE_TYPE,
|
|
44365
44419
|
SYSTEM_NOTIFICATION_SESSION_KEY: () => SYSTEM_NOTIFICATION_SESSION_KEY,
|
|
44366
44420
|
SessionBusyTracker: () => SessionBusyTracker,
|
|
44367
44421
|
SessionStore: () => SessionStore,
|
|
@@ -44407,7 +44461,9 @@ __export(index_exports, {
|
|
|
44407
44461
|
buildInboundTerminalExtras: () => buildInboundTerminalExtras,
|
|
44408
44462
|
buildLaunchdPlist: () => buildLaunchdPlist,
|
|
44409
44463
|
buildLauncherEntryJs: () => buildLauncherEntryJs,
|
|
44464
|
+
buildListJobsByVerifiedSenderArgs: () => buildListJobsByVerifiedSenderArgs,
|
|
44410
44465
|
buildMessageEligibleArgs: () => buildMessageEligibleArgs,
|
|
44466
|
+
buildRunLogFileName: () => buildRunLogFileName,
|
|
44411
44467
|
buildSchtasksCreateArgs: () => buildSchtasksCreateArgs,
|
|
44412
44468
|
buildSchtasksDeleteArgs: () => buildSchtasksDeleteArgs,
|
|
44413
44469
|
buildSchtasksEndArgs: () => buildSchtasksEndArgs,
|
|
@@ -44416,9 +44472,14 @@ __export(index_exports, {
|
|
|
44416
44472
|
buildSeaConfig: () => buildSeaConfig,
|
|
44417
44473
|
buildServicePath: () => buildServicePath,
|
|
44418
44474
|
buildSessionKey: () => buildSessionKey,
|
|
44475
|
+
buildSubscriptionEnvelope: () => buildSubscriptionEnvelope,
|
|
44476
|
+
buildSubscriptionInboundExtras: () => buildSubscriptionInboundExtras,
|
|
44477
|
+
buildSubscriptionJobExtras: () => buildSubscriptionJobExtras,
|
|
44478
|
+
buildSubscriptionSendExtras: () => buildSubscriptionSendExtras,
|
|
44419
44479
|
buildSystemMessageNotice: () => buildSystemMessageNotice,
|
|
44420
44480
|
buildSystemStoredMessage: () => buildSystemStoredMessage,
|
|
44421
44481
|
buildSystemdUserService: () => buildSystemdUserService,
|
|
44482
|
+
buildUpgradeRecommendationNotice: () => buildUpgradeRecommendationNotice,
|
|
44422
44483
|
buildWin32OnchainosCandidates: () => buildWin32OnchainosCandidates,
|
|
44423
44484
|
buildWindowsParentProcessProbe: () => buildWindowsParentProcessProbe,
|
|
44424
44485
|
buildXmtpMessageSentExtra: () => buildXmtpMessageSentExtra,
|
|
@@ -44433,6 +44494,7 @@ __export(index_exports, {
|
|
|
44433
44494
|
checkCodexReadiness: () => checkCodexReadiness,
|
|
44434
44495
|
claimActiveDaemon: () => claimActiveDaemon,
|
|
44435
44496
|
classifyJobBindingSource: () => classifyJobBindingSource,
|
|
44497
|
+
classifyListJobsError: () => classifyListJobsError,
|
|
44436
44498
|
clearCodexReadinessCache: () => clearCodexReadinessCache,
|
|
44437
44499
|
codexCommandResolvesWithoutOverride: () => codexCommandResolvesWithoutOverride,
|
|
44438
44500
|
codexReadinessCacheKey: () => codexReadinessCacheKey,
|
|
@@ -44444,10 +44506,12 @@ __export(index_exports, {
|
|
|
44444
44506
|
createOutboundBehavior: () => createOutboundBehavior,
|
|
44445
44507
|
createUserAttentionWatchParentMonitor: () => createUserAttentionWatchParentMonitor,
|
|
44446
44508
|
currentOpenClawGatewaySessionKey: () => currentOpenClawGatewaySessionKey,
|
|
44509
|
+
decideSubscriptionGate: () => decideSubscriptionGate,
|
|
44447
44510
|
detectAiProviders: () => detectAiProviders,
|
|
44448
44511
|
detectAiRuntimeSurface: () => detectAiRuntimeSurface,
|
|
44449
44512
|
detectCurrentAiProvider: () => detectCurrentAiProvider,
|
|
44450
44513
|
detectGatewayInvocation: () => detectGatewayInvocation,
|
|
44514
|
+
detectListJobsByVerifiedSenderSupport: () => detectListJobsByVerifiedSenderSupport,
|
|
44451
44515
|
detectMessageEligibleOfflineReplaySupport: () => detectMessageEligibleOfflineReplaySupport,
|
|
44452
44516
|
detectRuntime: () => detectRuntime,
|
|
44453
44517
|
ensureDaemonReady: () => ensureDaemonReady,
|
|
@@ -44461,6 +44525,7 @@ __export(index_exports, {
|
|
|
44461
44525
|
extractDirectToUserNotification: () => extractDirectToUserNotification,
|
|
44462
44526
|
extractRateLimitEndpoint: () => extractRateLimitEndpoint,
|
|
44463
44527
|
extractXmtpSentAtMs: () => extractXmtpSentAtMs2,
|
|
44528
|
+
fanOutSubscriptionJobs: () => fanOutSubscriptionJobs,
|
|
44464
44529
|
findWindowsNativeOkxA2aExe: () => findWindowsNativeOkxA2aExe,
|
|
44465
44530
|
followFile: () => followFile,
|
|
44466
44531
|
formatDoctorReportForHumans: () => formatDoctorReportForHumans,
|
|
@@ -44473,6 +44538,7 @@ __export(index_exports, {
|
|
|
44473
44538
|
getXmtpCreationCooldown: () => getXmtpCreationCooldown,
|
|
44474
44539
|
handleCapabilitiesCommand: () => handleCapabilitiesCommand,
|
|
44475
44540
|
handleDoctorCommand: () => handleDoctorCommand,
|
|
44541
|
+
handleSubscriptionPushCommand: () => handleSubscriptionPushCommand,
|
|
44476
44542
|
handleXmtpDebugCommand: () => handleXmtpDebugCommand,
|
|
44477
44543
|
handleXmtpSendCommand: () => handleXmtpSendCommand,
|
|
44478
44544
|
handleXmtpTestCommand: () => handleXmtpTestCommand,
|
|
@@ -44487,6 +44553,7 @@ __export(index_exports, {
|
|
|
44487
44553
|
invalidateResolvedOnchainosBinForTests: () => invalidateResolvedOnchainosBinForTests,
|
|
44488
44554
|
isAutostartManagerUnavailableError: () => isAutostartManagerUnavailableError,
|
|
44489
44555
|
isDefaultTaskHome: () => isDefaultTaskHome,
|
|
44556
|
+
isFingerprintKey: () => isFingerprintKey,
|
|
44490
44557
|
isGatewayAvailableForHeartbeat: () => isGatewayAvailableForHeartbeat,
|
|
44491
44558
|
isHermesGatewayPluginEnabled: () => isHermesGatewayPluginEnabled,
|
|
44492
44559
|
isInfoEventAllowlisted: () => isInfoEventAllowlisted,
|
|
@@ -44497,6 +44564,7 @@ __export(index_exports, {
|
|
|
44497
44564
|
isPrereleaseVersion: () => isPrereleaseVersion,
|
|
44498
44565
|
isRetryableOpenClawGatewayError: () => isRetryableOpenClawGatewayError,
|
|
44499
44566
|
isSqliteBusyError: () => isSqliteBusyError,
|
|
44567
|
+
isSubscriptionEnvelope: () => isSubscriptionEnvelope,
|
|
44500
44568
|
isSystemdManagerUnavailableMessage: () => isSystemdManagerUnavailableMessage,
|
|
44501
44569
|
isTagKey: () => isTagKey,
|
|
44502
44570
|
isValidExternalJobId: () => isValidExternalJobId,
|
|
@@ -44505,8 +44573,12 @@ __export(index_exports, {
|
|
|
44505
44573
|
killProcessTree: () => killProcessTree,
|
|
44506
44574
|
launchdPlistHasCurrentRestartPolicy: () => launchdPlistHasCurrentRestartPolicy,
|
|
44507
44575
|
listAllAgentsWithMetadata: () => listAllAgentsWithMetadata,
|
|
44576
|
+
listJobsByVerifiedSender: () => listJobsByVerifiedSender,
|
|
44577
|
+
listJobsByVerifiedSenderHelpAdvertisesCommand: () => listJobsByVerifiedSenderHelpAdvertisesCommand,
|
|
44578
|
+
listJobsByVerifiedSenderWithCapability: () => listJobsByVerifiedSenderWithCapability,
|
|
44508
44579
|
logWinCompat: () => logWinCompat,
|
|
44509
44580
|
logXmtpMessageSent: () => logXmtpMessageSent,
|
|
44581
|
+
logger: () => logger,
|
|
44510
44582
|
maybeRecommendOnchainosUpgrade: () => maybeRecommendOnchainosUpgrade,
|
|
44511
44583
|
mergeA2AEnvelopeTips: () => mergeA2AEnvelopeTips,
|
|
44512
44584
|
messageEligibleHelpAdvertisesOfflineReplay: () => messageEligibleHelpAdvertisesOfflineReplay,
|
|
@@ -44514,6 +44586,8 @@ __export(index_exports, {
|
|
|
44514
44586
|
normalizeAiProvider: () => normalizeAiProvider,
|
|
44515
44587
|
normalizeAiRuntimeProvider: () => normalizeAiRuntimeProvider,
|
|
44516
44588
|
normalizeHermesOkxA2aPluginConfig: () => normalizeHermesOkxA2aPluginConfig,
|
|
44589
|
+
normalizeListJobsResponse: () => normalizeListJobsResponse,
|
|
44590
|
+
normalizeSubscriptionJobs: () => normalizeSubscriptionJobs,
|
|
44517
44591
|
notifyAgentMessageToUserAttention: () => notifyAgentMessageToUserAttention,
|
|
44518
44592
|
notifyDirectToUserAttention: () => notifyDirectToUserAttention,
|
|
44519
44593
|
notifySystemMessageToUser: () => notifySystemMessageToUser,
|
|
@@ -44524,6 +44598,7 @@ __export(index_exports, {
|
|
|
44524
44598
|
parsePluginYamlVersion: () => parsePluginYamlVersion,
|
|
44525
44599
|
parseWalletLoginStatus: () => parseWalletLoginStatus,
|
|
44526
44600
|
parseWindowsParentProcessJson: () => parseWindowsParentProcessJson,
|
|
44601
|
+
partitionSubscriptionJobsByOwner: () => partitionSubscriptionJobsByOwner,
|
|
44527
44602
|
performRuntimeSwitch: () => performRuntimeSwitch,
|
|
44528
44603
|
persistAiRuntimeSurfaceBestEffort: () => persistAiRuntimeSurfaceBestEffort,
|
|
44529
44604
|
persistCurrentRuntimeSelectionForNewJob: () => persistCurrentRuntimeSelectionForNewJob,
|
|
@@ -44533,12 +44608,14 @@ __export(index_exports, {
|
|
|
44533
44608
|
printXmtpTestUsage: () => printXmtpTestUsage,
|
|
44534
44609
|
probeCodexAuthStatus: () => probeCodexAuthStatus,
|
|
44535
44610
|
processFileMessage: () => processFileMessage,
|
|
44611
|
+
processSubscriptionInbound: () => processSubscriptionInbound,
|
|
44536
44612
|
queryWalletLoginStatus: () => queryWalletLoginStatus,
|
|
44537
44613
|
readAiProviderTimeoutMs: () => readAiProviderTimeoutMs,
|
|
44538
44614
|
readAiRuntimeSurfaceBestEffort: () => readAiRuntimeSurfaceBestEffort,
|
|
44539
44615
|
readCachedCodexReadiness: () => readCachedCodexReadiness,
|
|
44540
44616
|
readLastLines: () => readLastLines,
|
|
44541
44617
|
readParentProcessCommandForPlatform: () => readParentProcessCommandForPlatform,
|
|
44618
|
+
readSubscriptionEnvelope: () => readSubscriptionEnvelope,
|
|
44542
44619
|
readUserAttentionWatcherEvent: () => readUserAttentionWatcherEvent,
|
|
44543
44620
|
refreshAgentsAndWait: () => refreshAgentsAndWait,
|
|
44544
44621
|
refreshOnchainosVersionMetadata: () => refreshOnchainosVersionMetadata,
|
|
@@ -44549,8 +44626,10 @@ __export(index_exports, {
|
|
|
44549
44626
|
replayScanBackoffWithJitterMs: () => replayScanBackoffWithJitterMs,
|
|
44550
44627
|
reportDoctorRunToSentry: () => reportDoctorRunToSentry,
|
|
44551
44628
|
reportUserNotificationFailure: () => reportUserNotificationFailure,
|
|
44629
|
+
resetListJobsByVerifiedSenderCapabilityForTests: () => resetListJobsByVerifiedSenderCapabilityForTests,
|
|
44552
44630
|
resetMessageEligibleOfflineReplayCapabilityForTests: () => resetMessageEligibleOfflineReplayCapabilityForTests,
|
|
44553
44631
|
resetResolvedOnchainosBinForTests: () => resetResolvedOnchainosBinForTests,
|
|
44632
|
+
resetSubscriptionTargetsForTests: () => resetSubscriptionTargetsForTests,
|
|
44554
44633
|
resetXmtpCreationCooldownForTests: () => resetXmtpCreationCooldownForTests,
|
|
44555
44634
|
resolveAiPermissionPreset: () => resolveAiPermissionPreset,
|
|
44556
44635
|
resolveAiProviderCommand: () => resolveAiProviderCommand,
|
|
@@ -44604,6 +44683,8 @@ __export(index_exports, {
|
|
|
44604
44683
|
stopOpenClawGateway: () => stopOpenClawGateway,
|
|
44605
44684
|
stopSystemdAutostart: () => stopSystemdAutostart,
|
|
44606
44685
|
subscribeUserAttentionEvents: () => subscribeUserAttentionEvents,
|
|
44686
|
+
subscriptionIdempotencyKey: () => subscriptionIdempotencyKey,
|
|
44687
|
+
summarizeSubscriptionPush: () => summarizeSubscriptionPush,
|
|
44607
44688
|
summarizeXmtpTestEvents: () => summarizeXmtpTestEvents,
|
|
44608
44689
|
switchProvider: () => switchProvider,
|
|
44609
44690
|
switchProviderWithReadinessGate: () => switchProviderWithReadinessGate,
|
|
@@ -44612,6 +44693,7 @@ __export(index_exports, {
|
|
|
44612
44693
|
tailFile: () => tailFile,
|
|
44613
44694
|
toOpenClawGatewaySessionKey: () => toOpenClawGatewaySessionKey,
|
|
44614
44695
|
toWindowsInvocation: () => toWindowsInvocation,
|
|
44696
|
+
tryMarkSubscriptionTarget: () => tryMarkSubscriptionTarget,
|
|
44615
44697
|
writeAiPermissionPresetToConfig: () => writeAiPermissionPresetToConfig
|
|
44616
44698
|
});
|
|
44617
44699
|
module.exports = __toCommonJS(index_exports);
|
|
@@ -44621,12 +44703,62 @@ init_autostart();
|
|
|
44621
44703
|
|
|
44622
44704
|
// src/ai-runner.ts
|
|
44623
44705
|
init_log();
|
|
44624
|
-
var
|
|
44706
|
+
var import_node_crypto5 = require("node:crypto");
|
|
44625
44707
|
var import_node_fs11 = require("node:fs");
|
|
44626
44708
|
var import_promises7 = require("node:fs/promises");
|
|
44627
44709
|
var import_node_os6 = require("node:os");
|
|
44628
44710
|
var import_node_path16 = require("node:path");
|
|
44629
44711
|
init_ai_command();
|
|
44712
|
+
|
|
44713
|
+
// src/ai-run-log-path.ts
|
|
44714
|
+
var import_node_crypto2 = require("node:crypto");
|
|
44715
|
+
var RUN_LOG_FILENAME_MAX_BYTES = 240;
|
|
44716
|
+
function buildRunLogFileName(request) {
|
|
44717
|
+
const source = request.source;
|
|
44718
|
+
const sessionKey = request.sessionKey;
|
|
44719
|
+
const messageId = request.messageId;
|
|
44720
|
+
const jobId = request.jobId;
|
|
44721
|
+
const safeMessageId = encodeURIComponent(messageId);
|
|
44722
|
+
const prefix = source === "job-dispatch" ? "ai-" : "ai-session-";
|
|
44723
|
+
const encodedContext = source === "job-dispatch" ? encodeURIComponent(jobId ?? "unknown") : encodeURIComponent(sessionKey);
|
|
44724
|
+
const readable = `${prefix}${encodedContext}-${safeMessageId}.log`;
|
|
44725
|
+
if (Buffer.byteLength(readable, "utf8") <= RUN_LOG_FILENAME_MAX_BYTES) {
|
|
44726
|
+
return readable;
|
|
44727
|
+
}
|
|
44728
|
+
const readableWithoutExt = readable.slice(0, -".log".length);
|
|
44729
|
+
const digest = (0, import_node_crypto2.createHash)("sha256").update(readableWithoutExt).digest("hex").slice(0, 24);
|
|
44730
|
+
const suffix = `-${digest}.log`;
|
|
44731
|
+
const budgetForContext = RUN_LOG_FILENAME_MAX_BYTES - Buffer.byteLength(prefix, "utf8") - Buffer.byteLength(suffix, "utf8");
|
|
44732
|
+
const contextHead = truncateToUtf8ByteBudgetSafe(encodedContext, Math.max(budgetForContext, 0));
|
|
44733
|
+
return `${prefix}${contextHead}${suffix}`;
|
|
44734
|
+
}
|
|
44735
|
+
function truncateToUtf8ByteBudgetSafe(encoded, maxBytes) {
|
|
44736
|
+
if (maxBytes <= 0) {
|
|
44737
|
+
return "";
|
|
44738
|
+
}
|
|
44739
|
+
if (Buffer.byteLength(encoded, "utf8") <= maxBytes) {
|
|
44740
|
+
return encoded;
|
|
44741
|
+
}
|
|
44742
|
+
let candidateLength = Math.min(maxBytes, encoded.length);
|
|
44743
|
+
while (candidateLength > 0) {
|
|
44744
|
+
const candidate = encoded.slice(0, candidateLength);
|
|
44745
|
+
if (!endsWithSplitEscape(candidate)) {
|
|
44746
|
+
return candidate;
|
|
44747
|
+
}
|
|
44748
|
+
candidateLength -= 1;
|
|
44749
|
+
}
|
|
44750
|
+
return "";
|
|
44751
|
+
}
|
|
44752
|
+
function endsWithSplitEscape(value) {
|
|
44753
|
+
const percentIndex = value.lastIndexOf("%");
|
|
44754
|
+
if (percentIndex === -1) {
|
|
44755
|
+
return false;
|
|
44756
|
+
}
|
|
44757
|
+
const tail = value.length - percentIndex - 1;
|
|
44758
|
+
return tail < 2;
|
|
44759
|
+
}
|
|
44760
|
+
|
|
44761
|
+
// src/ai-runner.ts
|
|
44630
44762
|
init_paths();
|
|
44631
44763
|
|
|
44632
44764
|
// src/file-store.ts
|
|
@@ -46307,13 +46439,15 @@ var AiRunner = class {
|
|
|
46307
46439
|
);
|
|
46308
46440
|
}
|
|
46309
46441
|
buildRunLogPath(request) {
|
|
46310
|
-
|
|
46311
|
-
|
|
46312
|
-
|
|
46313
|
-
|
|
46314
|
-
|
|
46315
|
-
|
|
46316
|
-
|
|
46442
|
+
return (0, import_node_path16.join)(
|
|
46443
|
+
this.logsDir,
|
|
46444
|
+
buildRunLogFileName({
|
|
46445
|
+
source: request.source,
|
|
46446
|
+
sessionKey: request.sessionKey,
|
|
46447
|
+
messageId: request.messageId,
|
|
46448
|
+
jobId: request.jobId
|
|
46449
|
+
})
|
|
46450
|
+
);
|
|
46317
46451
|
}
|
|
46318
46452
|
readRunAiSessionId(provider, request, file, sessionMeta) {
|
|
46319
46453
|
if (request.source === "job-dispatch" && request.jobId) {
|
|
@@ -48035,7 +48169,7 @@ function normalizeAttentionProvider(provider) {
|
|
|
48035
48169
|
return provider === "unknown" ? null : provider;
|
|
48036
48170
|
}
|
|
48037
48171
|
function stableHash(value) {
|
|
48038
|
-
return (0,
|
|
48172
|
+
return (0, import_node_crypto5.createHash)("sha256").update(value).digest("hex").slice(0, 24);
|
|
48039
48173
|
}
|
|
48040
48174
|
function formatCommand(args) {
|
|
48041
48175
|
return args.map(shellQuote).join(" ");
|
|
@@ -48062,10 +48196,11 @@ function shortenJobId(jobId) {
|
|
|
48062
48196
|
|
|
48063
48197
|
// src/command-store.ts
|
|
48064
48198
|
init_log();
|
|
48065
|
-
var
|
|
48199
|
+
var import_node_crypto6 = require("node:crypto");
|
|
48066
48200
|
var import_node_fs12 = require("node:fs");
|
|
48067
48201
|
var import_node_path17 = require("node:path");
|
|
48068
48202
|
init_paths();
|
|
48203
|
+
init_session_store();
|
|
48069
48204
|
var { DatabaseSync: DatabaseSync2 } = loadSqlite2();
|
|
48070
48205
|
var XMTP_DEBUG_RESULT_TTL_MS = 5 * 6e4;
|
|
48071
48206
|
function stringifyForStorage(value) {
|
|
@@ -48087,7 +48222,7 @@ var CommandStore = class {
|
|
|
48087
48222
|
}
|
|
48088
48223
|
createXmtpSendCommand(params) {
|
|
48089
48224
|
return {
|
|
48090
|
-
id: (0,
|
|
48225
|
+
id: (0, import_node_crypto6.randomUUID)(),
|
|
48091
48226
|
type: "xmtp-send",
|
|
48092
48227
|
jobId: params.jobId,
|
|
48093
48228
|
message: params.message,
|
|
@@ -48101,16 +48236,27 @@ var CommandStore = class {
|
|
|
48101
48236
|
createdAt: Date.now()
|
|
48102
48237
|
};
|
|
48103
48238
|
}
|
|
48239
|
+
createXmtpSubscriptionPushCommand(params) {
|
|
48240
|
+
return {
|
|
48241
|
+
id: (0, import_node_crypto6.randomUUID)(),
|
|
48242
|
+
type: "xmtp-subscription-push",
|
|
48243
|
+
myAgentId: params.myAgentId,
|
|
48244
|
+
content: params.content,
|
|
48245
|
+
conversationIds: params.conversationIds,
|
|
48246
|
+
deliveryId: params.deliveryId,
|
|
48247
|
+
createdAt: Date.now()
|
|
48248
|
+
};
|
|
48249
|
+
}
|
|
48104
48250
|
createXmtpGetPendingListCommand() {
|
|
48105
48251
|
return {
|
|
48106
|
-
id: (0,
|
|
48252
|
+
id: (0, import_node_crypto6.randomUUID)(),
|
|
48107
48253
|
type: "xmtp-get-pending-list",
|
|
48108
48254
|
createdAt: Date.now()
|
|
48109
48255
|
};
|
|
48110
48256
|
}
|
|
48111
48257
|
createXmtpDenyPendingConversationCommand(params) {
|
|
48112
48258
|
return {
|
|
48113
|
-
id: (0,
|
|
48259
|
+
id: (0, import_node_crypto6.randomUUID)(),
|
|
48114
48260
|
type: "xmtp-deny-pending-conversation",
|
|
48115
48261
|
groupId: params.groupId,
|
|
48116
48262
|
jobId: params.jobId,
|
|
@@ -48121,14 +48267,14 @@ var CommandStore = class {
|
|
|
48121
48267
|
}
|
|
48122
48268
|
createXmtpRefreshAgentsCommand() {
|
|
48123
48269
|
return {
|
|
48124
|
-
id: (0,
|
|
48270
|
+
id: (0, import_node_crypto6.randomUUID)(),
|
|
48125
48271
|
type: "xmtp-refresh-agents",
|
|
48126
48272
|
createdAt: Date.now()
|
|
48127
48273
|
};
|
|
48128
48274
|
}
|
|
48129
48275
|
createXmtpGetConversationHistoryCommand(params) {
|
|
48130
48276
|
return {
|
|
48131
|
-
id: (0,
|
|
48277
|
+
id: (0, import_node_crypto6.randomUUID)(),
|
|
48132
48278
|
type: "xmtp-get-conversation-history",
|
|
48133
48279
|
jobId: params.jobId,
|
|
48134
48280
|
toAgentId: params.toAgentId,
|
|
@@ -48140,7 +48286,7 @@ var CommandStore = class {
|
|
|
48140
48286
|
}
|
|
48141
48287
|
createXmtpDebugCommand(params) {
|
|
48142
48288
|
return {
|
|
48143
|
-
id: (0,
|
|
48289
|
+
id: (0, import_node_crypto6.randomUUID)(),
|
|
48144
48290
|
type: "xmtp-debug",
|
|
48145
48291
|
action: params.action,
|
|
48146
48292
|
groupId: params.groupId,
|
|
@@ -48155,7 +48301,7 @@ var CommandStore = class {
|
|
|
48155
48301
|
}
|
|
48156
48302
|
createAiJobMessageDispatchCommand(params) {
|
|
48157
48303
|
return {
|
|
48158
|
-
id: (0,
|
|
48304
|
+
id: (0, import_node_crypto6.randomUUID)(),
|
|
48159
48305
|
type: "ai-dispatch",
|
|
48160
48306
|
kind: "job-message",
|
|
48161
48307
|
jobId: params.jobId,
|
|
@@ -48166,7 +48312,7 @@ var CommandStore = class {
|
|
|
48166
48312
|
}
|
|
48167
48313
|
createAiSessionMessageDispatchCommand(params) {
|
|
48168
48314
|
return {
|
|
48169
|
-
id: (0,
|
|
48315
|
+
id: (0, import_node_crypto6.randomUUID)(),
|
|
48170
48316
|
type: "ai-dispatch",
|
|
48171
48317
|
kind: "session-message",
|
|
48172
48318
|
sessionKey: params.sessionKey,
|
|
@@ -48194,6 +48340,65 @@ var CommandStore = class {
|
|
|
48194
48340
|
);
|
|
48195
48341
|
return this.commandPath(command.id);
|
|
48196
48342
|
}
|
|
48343
|
+
/**
|
|
48344
|
+
* Atomic idempotent submit keyed on a business `idempotencyKey` (DEXMARKET-9035,
|
|
48345
|
+
* M2). The FIRST caller for a given key inserts its command and gets
|
|
48346
|
+
* `created: true`; every later caller with the SAME key — including after a
|
|
48347
|
+
* daemon / CommandStore rebuild — gets the ALREADY-persisted command back with
|
|
48348
|
+
* `created: false` and NO new row. Concurrency-safe: correctness rests on the
|
|
48349
|
+
* partial UNIQUE index on `idempotency_key`, not a check-then-insert (which
|
|
48350
|
+
* races), so a `INSERT ... ON CONFLICT DO NOTHING` collapses concurrent
|
|
48351
|
+
* duplicates to exactly one row. Recoverable SQLITE_BUSY/LOCKED errors reuse
|
|
48352
|
+
* the repo's bounded exponential backoff. This never changes the plain
|
|
48353
|
+
* `submit` path used by `xmtp-send` and every other daemon command.
|
|
48354
|
+
*/
|
|
48355
|
+
async submitIdempotent(command, idempotencyKey) {
|
|
48356
|
+
if (!idempotencyKey) {
|
|
48357
|
+
throw new Error("submitIdempotent requires a non-empty idempotencyKey");
|
|
48358
|
+
}
|
|
48359
|
+
return this.withBusyRetry(
|
|
48360
|
+
() => this.transaction(() => {
|
|
48361
|
+
const now = Date.now();
|
|
48362
|
+
const insert = this.db.prepare(`
|
|
48363
|
+
INSERT INTO command_queue (
|
|
48364
|
+
id, type, status, command_json, result_json,
|
|
48365
|
+
created_at_ms, updated_at_ms, processing_started_at_ms, completed_at_ms,
|
|
48366
|
+
idempotency_key
|
|
48367
|
+
)
|
|
48368
|
+
VALUES (?, ?, 'pending', ?, NULL, ?, ?, NULL, NULL, ?)
|
|
48369
|
+
ON CONFLICT(idempotency_key) WHERE idempotency_key IS NOT NULL DO NOTHING
|
|
48370
|
+
`).run(
|
|
48371
|
+
command.id,
|
|
48372
|
+
command.type,
|
|
48373
|
+
stringifyForStorage(command),
|
|
48374
|
+
normalizeCreatedAt(command.createdAt, now),
|
|
48375
|
+
now,
|
|
48376
|
+
idempotencyKey
|
|
48377
|
+
);
|
|
48378
|
+
if (Number(insert.changes ?? 0) > 0) {
|
|
48379
|
+
return { path: this.commandPath(command.id), commandId: command.id, created: true };
|
|
48380
|
+
}
|
|
48381
|
+
const existing = this.db.prepare(`
|
|
48382
|
+
SELECT id FROM command_queue WHERE idempotency_key = ?
|
|
48383
|
+
`).get(idempotencyKey);
|
|
48384
|
+
const existingId = existing?.id ?? command.id;
|
|
48385
|
+
return { path: this.commandPath(existingId), commandId: existingId, created: false };
|
|
48386
|
+
})
|
|
48387
|
+
);
|
|
48388
|
+
}
|
|
48389
|
+
async withBusyRetry(operation) {
|
|
48390
|
+
const attempts = 6;
|
|
48391
|
+
for (let attempt = 1; ; attempt += 1) {
|
|
48392
|
+
try {
|
|
48393
|
+
return operation();
|
|
48394
|
+
} catch (err) {
|
|
48395
|
+
if (!isSqliteBusyError(err) || attempt >= attempts) {
|
|
48396
|
+
throw err;
|
|
48397
|
+
}
|
|
48398
|
+
await new Promise((resolve11) => setTimeout(resolve11, Math.min(50 * 2 ** (attempt - 1), 1e3)));
|
|
48399
|
+
}
|
|
48400
|
+
}
|
|
48401
|
+
}
|
|
48197
48402
|
async listPending() {
|
|
48198
48403
|
return (await this.listPendingEntries()).map((entry) => entry.command);
|
|
48199
48404
|
}
|
|
@@ -48260,9 +48465,24 @@ var CommandStore = class {
|
|
|
48260
48465
|
CREATE INDEX IF NOT EXISTS idx_command_queue_status_created
|
|
48261
48466
|
ON command_queue(status, created_at_ms, id)
|
|
48262
48467
|
`);
|
|
48468
|
+
this.ensureColumn("command_queue", "idempotency_key", "TEXT");
|
|
48469
|
+
this.db.exec(`
|
|
48470
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_command_queue_idempotency_key
|
|
48471
|
+
ON command_queue(idempotency_key)
|
|
48472
|
+
WHERE idempotency_key IS NOT NULL
|
|
48473
|
+
`);
|
|
48263
48474
|
this.purgeExpiredXmtpDebugResults();
|
|
48264
48475
|
this.importLegacyFileCommands();
|
|
48265
48476
|
}
|
|
48477
|
+
ensureColumn(table, column, definition) {
|
|
48478
|
+
this.transaction(() => {
|
|
48479
|
+
const rows = this.db.prepare(`PRAGMA table_info(${table})`).all();
|
|
48480
|
+
if (rows.some((row) => row.name === column)) {
|
|
48481
|
+
return;
|
|
48482
|
+
}
|
|
48483
|
+
this.db.exec(`ALTER TABLE ${table} ADD COLUMN ${column} ${definition}`);
|
|
48484
|
+
});
|
|
48485
|
+
}
|
|
48266
48486
|
purgeExpiredXmtpDebugResults() {
|
|
48267
48487
|
this.db.prepare(`
|
|
48268
48488
|
DELETE FROM command_queue
|
|
@@ -48434,6 +48654,10 @@ function isDaemonCommand(value) {
|
|
|
48434
48654
|
if (parsed.type === "xmtp-send") {
|
|
48435
48655
|
return typeof parsed.jobId === "string" && typeof parsed.message === "string";
|
|
48436
48656
|
}
|
|
48657
|
+
if (parsed.type === "xmtp-subscription-push") {
|
|
48658
|
+
const command = parsed;
|
|
48659
|
+
return typeof command.myAgentId === "string" && typeof command.content === "string" && Array.isArray(command.conversationIds) && command.conversationIds.every((item) => typeof item === "string");
|
|
48660
|
+
}
|
|
48437
48661
|
if (parsed.type === "xmtp-get-pending-list") {
|
|
48438
48662
|
return true;
|
|
48439
48663
|
}
|
|
@@ -48600,7 +48824,7 @@ var import_node_path21 = require("node:path");
|
|
|
48600
48824
|
// ../../node_modules/@xmtp/node-sdk/dist/index.js
|
|
48601
48825
|
var import_node_bindings = require("@xmtp/node-bindings");
|
|
48602
48826
|
var import_node_bindings2 = require("@xmtp/node-bindings");
|
|
48603
|
-
var
|
|
48827
|
+
var import_node_crypto7 = require("node:crypto");
|
|
48604
48828
|
|
|
48605
48829
|
// ../../node_modules/@xmtp/node-sdk/node_modules/@xmtp/content-type-primitives/dist/index.js
|
|
48606
48830
|
var contentTypeToString = (contentType) => `${contentType.authorityId}/${contentType.typeId}:${contentType.versionMajor}.${contentType.versionMinor}`;
|
|
@@ -50322,7 +50546,7 @@ var resolveBackend = async (envOrBackend, gatewayHost) => {
|
|
|
50322
50546
|
return createBackend({ env: envOrBackend, gatewayHost });
|
|
50323
50547
|
};
|
|
50324
50548
|
var createEphemeralIdentifier = () => ({
|
|
50325
|
-
identifier: `0x${(0,
|
|
50549
|
+
identifier: `0x${(0, import_node_crypto7.randomBytes)(20).toString("hex")}`,
|
|
50326
50550
|
identifierKind: 0
|
|
50327
50551
|
});
|
|
50328
50552
|
var toInboxUpdatesCountMap = (value) => {
|
|
@@ -55112,7 +55336,7 @@ var sepolia = /* @__PURE__ */ defineChain({
|
|
|
55112
55336
|
});
|
|
55113
55337
|
|
|
55114
55338
|
// ../../node_modules/@xmtp/agent-sdk/dist/index.js
|
|
55115
|
-
var
|
|
55339
|
+
var import_node_crypto8 = require("node:crypto");
|
|
55116
55340
|
var version2 = "2.3.0";
|
|
55117
55341
|
var fromSelf = (message, client) => {
|
|
55118
55342
|
return message.senderInboxId === client.inboxId;
|
|
@@ -55807,7 +56031,7 @@ var Agent = class _Agent extends import_node_events.default {
|
|
|
55807
56031
|
return this.#client.accountIdentifier?.identifier;
|
|
55808
56032
|
}
|
|
55809
56033
|
};
|
|
55810
|
-
var CANCEL_ACTION_ID = (0,
|
|
56034
|
+
var CANCEL_ACTION_ID = (0, import_node_crypto8.randomUUID)();
|
|
55811
56035
|
var LimitedMap = class {
|
|
55812
56036
|
#map = /* @__PURE__ */ new Map();
|
|
55813
56037
|
#limit;
|
|
@@ -59481,7 +59705,7 @@ function buildSendEnvelope(params) {
|
|
|
59481
59705
|
init_log();
|
|
59482
59706
|
init_sentry_logger();
|
|
59483
59707
|
init_log_fields();
|
|
59484
|
-
var
|
|
59708
|
+
var import_node_crypto12 = require("node:crypto");
|
|
59485
59709
|
|
|
59486
59710
|
// ../core/src/a2a/concurrency.ts
|
|
59487
59711
|
async function withSharedPromise(registry, key, fn) {
|
|
@@ -60883,17 +61107,17 @@ init_ai_provider();
|
|
|
60883
61107
|
|
|
60884
61108
|
// src/agent-message-notice.ts
|
|
60885
61109
|
init_log();
|
|
60886
|
-
var
|
|
61110
|
+
var import_node_crypto11 = require("node:crypto");
|
|
60887
61111
|
init_session_store();
|
|
60888
61112
|
init_ai_provider();
|
|
60889
61113
|
|
|
60890
61114
|
// src/outbound-behavior.ts
|
|
60891
61115
|
init_log();
|
|
60892
|
-
var
|
|
61116
|
+
var import_node_crypto10 = require("node:crypto");
|
|
60893
61117
|
|
|
60894
61118
|
// src/openclaw-gateway.ts
|
|
60895
61119
|
init_log();
|
|
60896
|
-
var
|
|
61120
|
+
var import_node_crypto9 = require("node:crypto");
|
|
60897
61121
|
|
|
60898
61122
|
// ../core/src/openclaw-gateway-config.ts
|
|
60899
61123
|
var import_node_fs17 = require("node:fs");
|
|
@@ -61386,7 +61610,7 @@ async function callDeleteSessions(params) {
|
|
|
61386
61610
|
return await callOpenClawGateway({ method: "okx-a2a.delete_sessions", params });
|
|
61387
61611
|
}
|
|
61388
61612
|
async function callSessionsSend(params) {
|
|
61389
|
-
const idempotencyKey = params.idempotencyKey ?? (0,
|
|
61613
|
+
const idempotencyKey = params.idempotencyKey ?? (0, import_node_crypto9.randomUUID)();
|
|
61390
61614
|
const sendParams = { key: params.key, message: params.message, idempotencyKey };
|
|
61391
61615
|
try {
|
|
61392
61616
|
return await callOpenClawGateway({ method: "sessions.send", params: sendParams });
|
|
@@ -61502,7 +61726,7 @@ async function sleep3(ms) {
|
|
|
61502
61726
|
var MinimalGatewayClient = class {
|
|
61503
61727
|
config;
|
|
61504
61728
|
protocolVersion;
|
|
61505
|
-
instanceId = (0,
|
|
61729
|
+
instanceId = (0, import_node_crypto9.randomUUID)();
|
|
61506
61730
|
pending = /* @__PURE__ */ new Map();
|
|
61507
61731
|
ws = null;
|
|
61508
61732
|
ready = false;
|
|
@@ -61590,7 +61814,7 @@ var MinimalGatewayClient = class {
|
|
|
61590
61814
|
}));
|
|
61591
61815
|
}
|
|
61592
61816
|
const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
61593
|
-
const id = `okx-a2a-${++this.requestSeq}-${(0,
|
|
61817
|
+
const id = `okx-a2a-${++this.requestSeq}-${(0, import_node_crypto9.randomUUID)()}`;
|
|
61594
61818
|
const frame = { type: "req", id, method, params };
|
|
61595
61819
|
return new Promise((resolve11, reject) => {
|
|
61596
61820
|
const timer = setTimeout(() => {
|
|
@@ -61716,7 +61940,7 @@ function buildConnectParams(config, instanceId, protocolVersion) {
|
|
|
61716
61940
|
client: {
|
|
61717
61941
|
id: "gateway-client",
|
|
61718
61942
|
displayName: "okx-a2a-node",
|
|
61719
|
-
version: "0.2.
|
|
61943
|
+
version: "0.2.18-beta-4dd056b897-261015113839",
|
|
61720
61944
|
platform: "node",
|
|
61721
61945
|
mode: "backend",
|
|
61722
61946
|
instanceId
|
|
@@ -61727,7 +61951,7 @@ function buildConnectParams(config, instanceId, protocolVersion) {
|
|
|
61727
61951
|
commands: [],
|
|
61728
61952
|
permissions: {},
|
|
61729
61953
|
locale: Intl.DateTimeFormat().resolvedOptions().locale || "en-US",
|
|
61730
|
-
userAgent: `okx-a2a-node/${"0.2.
|
|
61954
|
+
userAgent: `okx-a2a-node/${"0.2.18-beta-4dd056b897-261015113839"}`,
|
|
61731
61955
|
auth: {
|
|
61732
61956
|
...config.token ? { token: config.token } : {},
|
|
61733
61957
|
...config.password ? { password: config.password } : {}
|
|
@@ -62333,7 +62557,7 @@ function resolveSessionGateFallbackMs(env = process.env) {
|
|
|
62333
62557
|
return DEFAULT_SESSION_GATE_FALLBACK_MS;
|
|
62334
62558
|
}
|
|
62335
62559
|
function resolveUserDeliveryId(input) {
|
|
62336
|
-
return input.idempotencyKey?.trim() || (0,
|
|
62560
|
+
return input.idempotencyKey?.trim() || (0, import_node_crypto10.randomUUID)();
|
|
62337
62561
|
}
|
|
62338
62562
|
var GATEWAY_RPC_TRANSPORT = "gateway_rpc";
|
|
62339
62563
|
var USER_CHANNEL_TRANSPORT = "user_channel";
|
|
@@ -63247,7 +63471,7 @@ function buildSystemMessageIdempotencyKey(input) {
|
|
|
63247
63471
|
return `system-message:${identity}`;
|
|
63248
63472
|
}
|
|
63249
63473
|
function stableHash2(value) {
|
|
63250
|
-
return (0,
|
|
63474
|
+
return (0, import_node_crypto11.createHash)("sha256").update(value).digest("hex").slice(0, 24);
|
|
63251
63475
|
}
|
|
63252
63476
|
|
|
63253
63477
|
// src/xmtp-send.ts
|
|
@@ -63716,7 +63940,7 @@ async function handleSqliteGroupSendCommand(params) {
|
|
|
63716
63940
|
role: senderAgent?.role,
|
|
63717
63941
|
sendDurationMs: Date.now() - sendStartMs
|
|
63718
63942
|
});
|
|
63719
|
-
const messageId = `outbound-${(0,
|
|
63943
|
+
const messageId = `outbound-${(0, import_node_crypto12.randomUUID)()}`;
|
|
63720
63944
|
await notifyAgentMessageToUserAttention({
|
|
63721
63945
|
direction: "outbound" /* OUTBOUND */,
|
|
63722
63946
|
sender: {
|
|
@@ -63837,7 +64061,7 @@ async function handleGroupSendCommand(params) {
|
|
|
63837
64061
|
sendDurationMs: Date.now() - sendStartMs
|
|
63838
64062
|
});
|
|
63839
64063
|
const now = Date.now();
|
|
63840
|
-
const messageId = `outbound-${(0,
|
|
64064
|
+
const messageId = `outbound-${(0, import_node_crypto12.randomUUID)()}`;
|
|
63841
64065
|
const stored = {
|
|
63842
64066
|
id: messageId,
|
|
63843
64067
|
direction: "outbound",
|
|
@@ -64056,7 +64280,7 @@ async function handleXmtpSendCommand(params) {
|
|
|
64056
64280
|
sendDurationMs: Date.now() - sendStartMs
|
|
64057
64281
|
});
|
|
64058
64282
|
const now = Date.now();
|
|
64059
|
-
const messageId = `outbound-${(0,
|
|
64283
|
+
const messageId = `outbound-${(0, import_node_crypto12.randomUUID)()}`;
|
|
64060
64284
|
const stored = {
|
|
64061
64285
|
id: messageId,
|
|
64062
64286
|
direction: "outbound",
|
|
@@ -64103,6 +64327,357 @@ async function handleXmtpSendCommand(params) {
|
|
|
64103
64327
|
}
|
|
64104
64328
|
}
|
|
64105
64329
|
|
|
64330
|
+
// src/subscription-push.ts
|
|
64331
|
+
init_log();
|
|
64332
|
+
init_sentry_logger();
|
|
64333
|
+
|
|
64334
|
+
// ../core/src/a2a/subscription-types.ts
|
|
64335
|
+
var SUBSCRIPTION_MESSAGE_TYPE = "a2a-subscription-push";
|
|
64336
|
+
|
|
64337
|
+
// ../core/src/a2a/subscription-envelope.ts
|
|
64338
|
+
function isPlainObject2(value) {
|
|
64339
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
64340
|
+
}
|
|
64341
|
+
function buildSubscriptionEnvelope(params) {
|
|
64342
|
+
const envelope = {
|
|
64343
|
+
msgType: SUBSCRIPTION_MESSAGE_TYPE,
|
|
64344
|
+
content: params.content,
|
|
64345
|
+
senderAgentId: params.senderAgentId
|
|
64346
|
+
};
|
|
64347
|
+
if (params.deliveryId) {
|
|
64348
|
+
envelope.deliveryId = params.deliveryId;
|
|
64349
|
+
}
|
|
64350
|
+
return JSON.stringify(envelope);
|
|
64351
|
+
}
|
|
64352
|
+
function isSubscriptionEnvelope(payload) {
|
|
64353
|
+
return isPlainObject2(payload) && payload.msgType === SUBSCRIPTION_MESSAGE_TYPE;
|
|
64354
|
+
}
|
|
64355
|
+
function isNonEmptyString(value) {
|
|
64356
|
+
return typeof value === "string" && value.length > 0;
|
|
64357
|
+
}
|
|
64358
|
+
function readSubscriptionEnvelope(payload) {
|
|
64359
|
+
if (!isSubscriptionEnvelope(payload)) {
|
|
64360
|
+
return { ok: false, reason: "not_subscription" };
|
|
64361
|
+
}
|
|
64362
|
+
const record = payload;
|
|
64363
|
+
if (!isNonEmptyString(record.content)) {
|
|
64364
|
+
return { ok: false, reason: "missing_content" };
|
|
64365
|
+
}
|
|
64366
|
+
const envelope = {
|
|
64367
|
+
msgType: SUBSCRIPTION_MESSAGE_TYPE,
|
|
64368
|
+
content: record.content,
|
|
64369
|
+
senderAgentId: isNonEmptyString(record.senderAgentId) ? record.senderAgentId : ""
|
|
64370
|
+
};
|
|
64371
|
+
if (isNonEmptyString(record.deliveryId)) {
|
|
64372
|
+
envelope.deliveryId = record.deliveryId;
|
|
64373
|
+
}
|
|
64374
|
+
return { ok: true, envelope };
|
|
64375
|
+
}
|
|
64376
|
+
|
|
64377
|
+
// src/subscription-telemetry.ts
|
|
64378
|
+
init_log_fields();
|
|
64379
|
+
var SUBSCRIPTION_TRANSPORT = "xmtp";
|
|
64380
|
+
function definedExtras(input) {
|
|
64381
|
+
return Object.entries(input).reduce((out, [key, value]) => {
|
|
64382
|
+
if (typeof value === "string" && value.trim().length > 0) {
|
|
64383
|
+
out[key] = value.trim();
|
|
64384
|
+
}
|
|
64385
|
+
return out;
|
|
64386
|
+
}, {});
|
|
64387
|
+
}
|
|
64388
|
+
function countExtras(input) {
|
|
64389
|
+
return Object.entries(input).reduce((out, [key, value]) => {
|
|
64390
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
64391
|
+
out[key] = String(value);
|
|
64392
|
+
}
|
|
64393
|
+
return out;
|
|
64394
|
+
}, {});
|
|
64395
|
+
}
|
|
64396
|
+
function buildSubscriptionSendExtras(input) {
|
|
64397
|
+
return {
|
|
64398
|
+
stage: input.checkpoint,
|
|
64399
|
+
...logFieldExtras({
|
|
64400
|
+
checkpoint: input.checkpoint,
|
|
64401
|
+
outcome: input.outcome ?? null,
|
|
64402
|
+
transport: SUBSCRIPTION_TRANSPORT,
|
|
64403
|
+
eventFamily: "outbound",
|
|
64404
|
+
deliveryId: input.deliveryId ?? null
|
|
64405
|
+
}),
|
|
64406
|
+
...definedExtras({
|
|
64407
|
+
aspAgentId: input.aspAgentId,
|
|
64408
|
+
conversationId: input.conversationId,
|
|
64409
|
+
reason: input.reason
|
|
64410
|
+
}),
|
|
64411
|
+
...countExtras({
|
|
64412
|
+
targetCount: input.targetCount,
|
|
64413
|
+
sentCount: input.sentCount,
|
|
64414
|
+
failedCount: input.failedCount,
|
|
64415
|
+
notGroupCount: input.notGroupCount
|
|
64416
|
+
})
|
|
64417
|
+
};
|
|
64418
|
+
}
|
|
64419
|
+
function buildSubscriptionInboundExtras(input) {
|
|
64420
|
+
return {
|
|
64421
|
+
stage: input.checkpoint,
|
|
64422
|
+
...logFieldExtras({
|
|
64423
|
+
checkpoint: input.checkpoint,
|
|
64424
|
+
outcome: input.outcome ?? null,
|
|
64425
|
+
transport: SUBSCRIPTION_TRANSPORT,
|
|
64426
|
+
eventFamily: "inbound",
|
|
64427
|
+
deliveryId: input.deliveryId ?? null
|
|
64428
|
+
}),
|
|
64429
|
+
...definedExtras({
|
|
64430
|
+
userAgentId: input.userAgentId,
|
|
64431
|
+
conversationId: input.conversationId,
|
|
64432
|
+
messageId: input.messageId,
|
|
64433
|
+
senderInboxId: input.senderInboxId,
|
|
64434
|
+
reason: input.reason,
|
|
64435
|
+
errorCode: input.errorCode
|
|
64436
|
+
}),
|
|
64437
|
+
...countExtras({
|
|
64438
|
+
returnedCount: input.returnedCount,
|
|
64439
|
+
invalidCount: input.invalidCount,
|
|
64440
|
+
ownedCount: input.ownedCount,
|
|
64441
|
+
ignoredCount: input.ignoredCount
|
|
64442
|
+
})
|
|
64443
|
+
};
|
|
64444
|
+
}
|
|
64445
|
+
function buildSubscriptionJobExtras(input) {
|
|
64446
|
+
return {
|
|
64447
|
+
stage: input.checkpoint,
|
|
64448
|
+
...logFieldExtras({
|
|
64449
|
+
checkpoint: input.checkpoint,
|
|
64450
|
+
outcome: input.outcome,
|
|
64451
|
+
transport: SUBSCRIPTION_TRANSPORT,
|
|
64452
|
+
eventFamily: "dispatch",
|
|
64453
|
+
deliveryId: input.deliveryId ?? null
|
|
64454
|
+
}),
|
|
64455
|
+
...definedExtras({
|
|
64456
|
+
jobId: input.jobId,
|
|
64457
|
+
userAgentId: input.userAgentId,
|
|
64458
|
+
aspAgentId: input.aspAgentId,
|
|
64459
|
+
conversationId: input.conversationId,
|
|
64460
|
+
reason: input.reason
|
|
64461
|
+
}),
|
|
64462
|
+
...countExtras({
|
|
64463
|
+
total: input.total,
|
|
64464
|
+
started: input.started,
|
|
64465
|
+
failed: input.failed,
|
|
64466
|
+
skippedDuplicate: input.skippedDuplicate
|
|
64467
|
+
})
|
|
64468
|
+
};
|
|
64469
|
+
}
|
|
64470
|
+
|
|
64471
|
+
// src/subscription-push.ts
|
|
64472
|
+
var DEFAULT_CONCURRENCY = 20;
|
|
64473
|
+
var conversationSyncPromises2 = /* @__PURE__ */ new WeakMap();
|
|
64474
|
+
function describeError(err) {
|
|
64475
|
+
if (err instanceof Error) {
|
|
64476
|
+
return err.message;
|
|
64477
|
+
}
|
|
64478
|
+
if (typeof err === "string" && err.length > 0) {
|
|
64479
|
+
return err;
|
|
64480
|
+
}
|
|
64481
|
+
return "unknown error";
|
|
64482
|
+
}
|
|
64483
|
+
async function requireXmtpClient2(service, address) {
|
|
64484
|
+
const existing = service.getClientByAddress(address);
|
|
64485
|
+
if (existing) {
|
|
64486
|
+
return existing;
|
|
64487
|
+
}
|
|
64488
|
+
await service.refreshAgents();
|
|
64489
|
+
const refreshed = service.getClientByAddress(address);
|
|
64490
|
+
if (!refreshed) {
|
|
64491
|
+
throw new Error(`no XMTP client found for ${address}`);
|
|
64492
|
+
}
|
|
64493
|
+
return refreshed;
|
|
64494
|
+
}
|
|
64495
|
+
function resolveLocalAddress(service, myAgentId) {
|
|
64496
|
+
const address = service.getAddressByAgentId(myAgentId);
|
|
64497
|
+
if (!address) {
|
|
64498
|
+
throw new Error(`No local communication address found for myAgentId=${myAgentId}`);
|
|
64499
|
+
}
|
|
64500
|
+
return address;
|
|
64501
|
+
}
|
|
64502
|
+
async function syncConversationsOnLocalMiss2(agent) {
|
|
64503
|
+
const conversations = agent.client.conversations;
|
|
64504
|
+
const existing = conversationSyncPromises2.get(conversations);
|
|
64505
|
+
if (existing) {
|
|
64506
|
+
return existing;
|
|
64507
|
+
}
|
|
64508
|
+
const pending = conversations.sync();
|
|
64509
|
+
conversationSyncPromises2.set(conversations, pending);
|
|
64510
|
+
try {
|
|
64511
|
+
await pending;
|
|
64512
|
+
} finally {
|
|
64513
|
+
if (conversationSyncPromises2.get(conversations) === pending) {
|
|
64514
|
+
conversationSyncPromises2.delete(conversations);
|
|
64515
|
+
}
|
|
64516
|
+
}
|
|
64517
|
+
}
|
|
64518
|
+
async function findGroupConversation2(agent, conversationId) {
|
|
64519
|
+
let conversation = await agent.client.conversations.getConversationById(conversationId);
|
|
64520
|
+
if (!(conversation instanceof Group)) {
|
|
64521
|
+
await syncConversationsOnLocalMiss2(agent);
|
|
64522
|
+
conversation = await agent.client.conversations.getConversationById(conversationId);
|
|
64523
|
+
}
|
|
64524
|
+
return conversation instanceof Group ? conversation : null;
|
|
64525
|
+
}
|
|
64526
|
+
async function sendSubscriptionToGroup(params) {
|
|
64527
|
+
const { agent, conversationId, command, myXmtpAddress, senderRole } = params;
|
|
64528
|
+
let conversation;
|
|
64529
|
+
try {
|
|
64530
|
+
conversation = await findGroupConversation2(agent, conversationId);
|
|
64531
|
+
} catch (err) {
|
|
64532
|
+
return { conversationId, status: "not_group", error: describeError(err) };
|
|
64533
|
+
}
|
|
64534
|
+
if (!conversation) {
|
|
64535
|
+
return {
|
|
64536
|
+
conversationId,
|
|
64537
|
+
status: "not_group",
|
|
64538
|
+
error: `conversationId=${conversationId} is not a Group (DM or unknown conversation)`
|
|
64539
|
+
};
|
|
64540
|
+
}
|
|
64541
|
+
const envelope = buildSubscriptionEnvelope({
|
|
64542
|
+
content: command.content,
|
|
64543
|
+
senderAgentId: command.myAgentId,
|
|
64544
|
+
deliveryId: command.deliveryId
|
|
64545
|
+
});
|
|
64546
|
+
const sendStartMs = Date.now();
|
|
64547
|
+
try {
|
|
64548
|
+
const xmtpMessageId = await conversation.sendText(envelope);
|
|
64549
|
+
logXmtpMessageSent({
|
|
64550
|
+
xmtpMessageId,
|
|
64551
|
+
conversationId,
|
|
64552
|
+
// V2 has no job dimension (FR-1) — deliveryId (or a fixed marker)
|
|
64553
|
+
// stands in for the telemetry taxonomy's jobId slot.
|
|
64554
|
+
jobId: command.deliveryId ?? "subscription-push",
|
|
64555
|
+
chatType: "group",
|
|
64556
|
+
component: "node_xmtp_subscription_push",
|
|
64557
|
+
myXmtpAddress,
|
|
64558
|
+
senderAgentId: command.myAgentId,
|
|
64559
|
+
role: senderRole,
|
|
64560
|
+
sendDurationMs: Date.now() - sendStartMs
|
|
64561
|
+
});
|
|
64562
|
+
const messageId = typeof xmtpMessageId === "string" && xmtpMessageId.length > 0 ? xmtpMessageId : String(xmtpMessageId);
|
|
64563
|
+
logWithTimestamp(
|
|
64564
|
+
`[okx-agent-task] subscription-push sent conversationId=${conversationId} deliveryId=${command.deliveryId ?? "(none)"}`
|
|
64565
|
+
);
|
|
64566
|
+
return { conversationId, status: "sent", messageId };
|
|
64567
|
+
} catch (err) {
|
|
64568
|
+
logWithTimestamp(
|
|
64569
|
+
`[okx-agent-task] subscription-push failed conversationId=${conversationId} deliveryId=${command.deliveryId ?? "(none)"}`
|
|
64570
|
+
);
|
|
64571
|
+
return { conversationId, status: "failed", error: describeError(err) };
|
|
64572
|
+
}
|
|
64573
|
+
}
|
|
64574
|
+
function summarizeSubscriptionPush(results) {
|
|
64575
|
+
let sentCount = 0;
|
|
64576
|
+
let failedCount = 0;
|
|
64577
|
+
for (const result of results) {
|
|
64578
|
+
if (result.status === "sent") {
|
|
64579
|
+
sentCount++;
|
|
64580
|
+
} else {
|
|
64581
|
+
failedCount++;
|
|
64582
|
+
}
|
|
64583
|
+
}
|
|
64584
|
+
return { conversationCount: results.length, sentCount, failedCount };
|
|
64585
|
+
}
|
|
64586
|
+
async function handleSubscriptionPushCommand(params) {
|
|
64587
|
+
const { command, service } = params;
|
|
64588
|
+
const aspAgentId = command.myAgentId;
|
|
64589
|
+
const deliveryId = command.deliveryId;
|
|
64590
|
+
const conversationIds = command.conversationIds ?? [];
|
|
64591
|
+
logger.info(
|
|
64592
|
+
LogEvent.SUBSCRIPTION_PUSH_STARTED,
|
|
64593
|
+
buildSubscriptionSendExtras({
|
|
64594
|
+
checkpoint: "outbound/subscription_push_started",
|
|
64595
|
+
aspAgentId,
|
|
64596
|
+
deliveryId,
|
|
64597
|
+
targetCount: conversationIds.length
|
|
64598
|
+
})
|
|
64599
|
+
);
|
|
64600
|
+
if (conversationIds.length === 0) {
|
|
64601
|
+
logger.info(
|
|
64602
|
+
LogEvent.SUBSCRIPTION_PUSH_EMPTY_TARGETS,
|
|
64603
|
+
buildSubscriptionSendExtras({
|
|
64604
|
+
checkpoint: "outbound/subscription_push_empty_targets",
|
|
64605
|
+
outcome: "ignored",
|
|
64606
|
+
aspAgentId,
|
|
64607
|
+
deliveryId,
|
|
64608
|
+
targetCount: 0,
|
|
64609
|
+
reason: "empty_targets"
|
|
64610
|
+
})
|
|
64611
|
+
);
|
|
64612
|
+
return { conversationCount: 0, sentCount: 0, failedCount: 0, results: [] };
|
|
64613
|
+
}
|
|
64614
|
+
const myXmtpAddress = resolveLocalAddress(service, command.myAgentId);
|
|
64615
|
+
const agent = await requireXmtpClient2(service, myXmtpAddress);
|
|
64616
|
+
const senderRole = service.getAgentByAddress?.(myXmtpAddress)?.role;
|
|
64617
|
+
logger.info(
|
|
64618
|
+
LogEvent.SUBSCRIPTION_PUSH_TARGETS_RESOLVED,
|
|
64619
|
+
buildSubscriptionSendExtras({
|
|
64620
|
+
checkpoint: "outbound/subscription_push_targets_resolved",
|
|
64621
|
+
aspAgentId,
|
|
64622
|
+
deliveryId,
|
|
64623
|
+
targetCount: conversationIds.length
|
|
64624
|
+
})
|
|
64625
|
+
);
|
|
64626
|
+
const settled = await parallelMap(
|
|
64627
|
+
conversationIds,
|
|
64628
|
+
(conversationId) => sendSubscriptionToGroup({
|
|
64629
|
+
agent,
|
|
64630
|
+
conversationId,
|
|
64631
|
+
command,
|
|
64632
|
+
myXmtpAddress,
|
|
64633
|
+
senderRole
|
|
64634
|
+
}),
|
|
64635
|
+
DEFAULT_CONCURRENCY
|
|
64636
|
+
);
|
|
64637
|
+
const results = settled.map((outcome, index2) => {
|
|
64638
|
+
if (outcome.status === "fulfilled") {
|
|
64639
|
+
return outcome.value;
|
|
64640
|
+
}
|
|
64641
|
+
return {
|
|
64642
|
+
conversationId: conversationIds[index2],
|
|
64643
|
+
status: "failed",
|
|
64644
|
+
error: describeError(outcome.reason)
|
|
64645
|
+
};
|
|
64646
|
+
});
|
|
64647
|
+
for (const result of results) {
|
|
64648
|
+
if (result.status === "sent") {
|
|
64649
|
+
continue;
|
|
64650
|
+
}
|
|
64651
|
+
logger.error(
|
|
64652
|
+
LogEvent.SUBSCRIPTION_PUSH_TARGET_FAILED,
|
|
64653
|
+
void 0,
|
|
64654
|
+
buildSubscriptionSendExtras({
|
|
64655
|
+
checkpoint: "outbound/subscription_push_target_failed",
|
|
64656
|
+
outcome: "failed",
|
|
64657
|
+
aspAgentId,
|
|
64658
|
+
deliveryId,
|
|
64659
|
+
conversationId: result.conversationId,
|
|
64660
|
+
reason: result.status
|
|
64661
|
+
})
|
|
64662
|
+
);
|
|
64663
|
+
}
|
|
64664
|
+
const summary = summarizeSubscriptionPush(results);
|
|
64665
|
+
const summaryOutcome = summary.failedCount === 0 ? "success" : summary.sentCount > 0 ? "partial" : "failed";
|
|
64666
|
+
logger.info(
|
|
64667
|
+
LogEvent.SUBSCRIPTION_PUSH_SUMMARY,
|
|
64668
|
+
buildSubscriptionSendExtras({
|
|
64669
|
+
checkpoint: "outbound/subscription_push_summary",
|
|
64670
|
+
outcome: summaryOutcome,
|
|
64671
|
+
aspAgentId,
|
|
64672
|
+
deliveryId,
|
|
64673
|
+
targetCount: summary.conversationCount,
|
|
64674
|
+
sentCount: summary.sentCount,
|
|
64675
|
+
failedCount: summary.failedCount
|
|
64676
|
+
})
|
|
64677
|
+
);
|
|
64678
|
+
return { ...summary, results };
|
|
64679
|
+
}
|
|
64680
|
+
|
|
64106
64681
|
// src/command-processor.ts
|
|
64107
64682
|
init_session_store();
|
|
64108
64683
|
init_ai_provider();
|
|
@@ -64783,6 +65358,9 @@ function commandSentryExtra(command, extra = {}) {
|
|
|
64783
65358
|
base.myAgentId = command.myAgentId ?? "";
|
|
64784
65359
|
base.toAgentId = command.toAgentId ?? "";
|
|
64785
65360
|
base.toXmtpAddress = command.toXmtpAddress ?? "";
|
|
65361
|
+
} else if (command.type === "xmtp-subscription-push") {
|
|
65362
|
+
base.myAgentId = command.myAgentId;
|
|
65363
|
+
base.conversationCount = command.conversationIds.length;
|
|
64786
65364
|
} else if (command.type === "xmtp-deny-pending-conversation") {
|
|
64787
65365
|
base.groupId = command.groupId;
|
|
64788
65366
|
base.jobId = command.jobId ?? "";
|
|
@@ -65138,6 +65716,10 @@ async function handleDaemonCommand(command, params) {
|
|
|
65138
65716
|
});
|
|
65139
65717
|
return { ok: true, messageId: result.messageId };
|
|
65140
65718
|
}
|
|
65719
|
+
if (command.type === "xmtp-subscription-push") {
|
|
65720
|
+
const result = await handleSubscriptionPushCommand({ command, service: params.service });
|
|
65721
|
+
return { ok: true, payload: result };
|
|
65722
|
+
}
|
|
65141
65723
|
if (command.type === "xmtp-get-pending-list") {
|
|
65142
65724
|
return { ok: true, payload: await listPendingTaskRequests(params) };
|
|
65143
65725
|
}
|
|
@@ -65220,12 +65802,12 @@ async function listPendingTaskRequests(params) {
|
|
|
65220
65802
|
}
|
|
65221
65803
|
async function denyPendingConversationsByJobId(jobId, params, content) {
|
|
65222
65804
|
const pending = await listPendingTaskRequests(params);
|
|
65223
|
-
const matched = pending.filter((item) =>
|
|
65805
|
+
const matched = pending.filter((item) => isPlainObject3(item) && readString2(item.jobId) === jobId);
|
|
65224
65806
|
const clientAddresses = [...params.service.getClients().keys()];
|
|
65225
65807
|
const targetsByKey = collectDenyTargetsFromPending(matched, clientAddresses);
|
|
65226
65808
|
const groupIds = /* @__PURE__ */ new Set();
|
|
65227
65809
|
for (const item of matched) {
|
|
65228
|
-
if (!
|
|
65810
|
+
if (!isPlainObject3(item)) {
|
|
65229
65811
|
continue;
|
|
65230
65812
|
}
|
|
65231
65813
|
const groupId = readString2(item.groupId);
|
|
@@ -65252,7 +65834,7 @@ async function denyPendingConversationsByJobId(jobId, params, content) {
|
|
|
65252
65834
|
function collectDenyTargetsFromPending(pending, fallbackAddresses) {
|
|
65253
65835
|
const targetsByKey = /* @__PURE__ */ new Map();
|
|
65254
65836
|
for (const item of pending) {
|
|
65255
|
-
if (!
|
|
65837
|
+
if (!isPlainObject3(item)) {
|
|
65256
65838
|
continue;
|
|
65257
65839
|
}
|
|
65258
65840
|
const groupId = readString2(item.groupId);
|
|
@@ -65277,7 +65859,7 @@ ${groupId}`, {
|
|
|
65277
65859
|
async function resolvePendingTargetsByGroupId(groupId, addresses, params) {
|
|
65278
65860
|
const addressSet = addresses ? new Set(addresses) : null;
|
|
65279
65861
|
const pending = (await listPendingTaskRequests(params)).filter((item) => {
|
|
65280
|
-
if (!
|
|
65862
|
+
if (!isPlainObject3(item) || readString2(item.groupId) !== groupId) {
|
|
65281
65863
|
return false;
|
|
65282
65864
|
}
|
|
65283
65865
|
const address = readString2(item.myXmtpAddress);
|
|
@@ -65397,7 +65979,7 @@ function filterKnownPendingGroups(items, sessionStore) {
|
|
|
65397
65979
|
return items;
|
|
65398
65980
|
}
|
|
65399
65981
|
return items.filter((item) => {
|
|
65400
|
-
if (!
|
|
65982
|
+
if (!isPlainObject3(item)) {
|
|
65401
65983
|
return true;
|
|
65402
65984
|
}
|
|
65403
65985
|
const jobId = readString2(item.jobId);
|
|
@@ -65408,7 +65990,7 @@ function filterKnownPendingGroups(items, sessionStore) {
|
|
|
65408
65990
|
return sessionStore.querySessions({ jobId, toAgentId, limit: 1 }).length === 0;
|
|
65409
65991
|
});
|
|
65410
65992
|
}
|
|
65411
|
-
function
|
|
65993
|
+
function isPlainObject3(value) {
|
|
65412
65994
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
65413
65995
|
}
|
|
65414
65996
|
function readString2(value) {
|
|
@@ -65542,6 +66124,10 @@ function formatCommandCompleted(command, result) {
|
|
|
65542
66124
|
if (command.type === "xmtp-send") {
|
|
65543
66125
|
return `[okx-agent-task] xmtp-send command completed id=${command.id} job=${command.jobId} messageId=${result.messageId}`;
|
|
65544
66126
|
}
|
|
66127
|
+
if (command.type === "xmtp-subscription-push") {
|
|
66128
|
+
const payload = isPlainObject3(result.payload) ? result.payload : {};
|
|
66129
|
+
return `[okx-agent-task] xmtp-subscription-push command completed id=${command.id} deliveryId=${command.deliveryId ?? "(none)"} conversationCount=${payload.conversationCount ?? 0} sentCount=${payload.sentCount ?? 0} failedCount=${payload.failedCount ?? 0}`;
|
|
66130
|
+
}
|
|
65545
66131
|
if (command.type === "xmtp-get-pending-list") {
|
|
65546
66132
|
return `[okx-agent-task] xmtp-get-pending-list command completed id=${command.id}`;
|
|
65547
66133
|
}
|
|
@@ -65562,8 +66148,8 @@ function formatCommandCompleted(command, result) {
|
|
|
65562
66148
|
return `[okx-agent-task] xmtp-refresh-agents command completed id=${command.id}`;
|
|
65563
66149
|
}
|
|
65564
66150
|
function formatXmtpDebugCompleted(command, payload) {
|
|
65565
|
-
const record =
|
|
65566
|
-
const summary =
|
|
66151
|
+
const record = isPlainObject3(payload) ? payload : {};
|
|
66152
|
+
const summary = isPlainObject3(record.summary) ? record.summary : {};
|
|
65567
66153
|
const count = command.action === "group-list" ? record.groupCount ?? 0 : command.action === "group-inspect" ? record.conversationFound ? 1 : 0 : summary.matchedCount ?? 0;
|
|
65568
66154
|
return `[okx-agent-task] xmtp-debug command completed id=${command.id} action=${command.action} rows=${String(count)}`;
|
|
65569
66155
|
}
|
|
@@ -65718,12 +66304,393 @@ function trimForUser2(value) {
|
|
|
65718
66304
|
|
|
65719
66305
|
// src/message-handler.ts
|
|
65720
66306
|
init_log();
|
|
65721
|
-
var
|
|
66307
|
+
var import_node_crypto13 = require("node:crypto");
|
|
65722
66308
|
init_sentry_logger();
|
|
65723
66309
|
init_log_fields();
|
|
65724
66310
|
init_paths();
|
|
65725
66311
|
init_session_store();
|
|
65726
66312
|
init_ai_provider();
|
|
66313
|
+
|
|
66314
|
+
// src/subscription-inbound.ts
|
|
66315
|
+
init_log();
|
|
66316
|
+
function decideSubscriptionGate(input) {
|
|
66317
|
+
if (!isSubscriptionEnvelope(input.payload)) {
|
|
66318
|
+
return { kind: "not_subscription" };
|
|
66319
|
+
}
|
|
66320
|
+
if (input.chatType === "dm") {
|
|
66321
|
+
return { kind: "drop", reason: "dm_subscription" };
|
|
66322
|
+
}
|
|
66323
|
+
if (input.chatType === "unknown") {
|
|
66324
|
+
return { kind: "drop", reason: "unknown_conversation_subscription" };
|
|
66325
|
+
}
|
|
66326
|
+
const read = readSubscriptionEnvelope(input.payload);
|
|
66327
|
+
if (!read.ok) {
|
|
66328
|
+
return { kind: "drop", reason: "invalid_envelope", detail: read.reason };
|
|
66329
|
+
}
|
|
66330
|
+
if (!input.senderInboxId) {
|
|
66331
|
+
return { kind: "drop", reason: "missing_sender_inbox_id" };
|
|
66332
|
+
}
|
|
66333
|
+
return { kind: "v2", envelope: read.envelope };
|
|
66334
|
+
}
|
|
66335
|
+
function partitionSubscriptionJobsByOwner(input) {
|
|
66336
|
+
const owned = [];
|
|
66337
|
+
for (const job of input.jobs) {
|
|
66338
|
+
if (job.userAgentId === input.localAgentId) {
|
|
66339
|
+
owned.push(job);
|
|
66340
|
+
}
|
|
66341
|
+
}
|
|
66342
|
+
return {
|
|
66343
|
+
owned,
|
|
66344
|
+
returnedCount: input.jobs.length,
|
|
66345
|
+
ownedCount: owned.length,
|
|
66346
|
+
ignoredCount: input.jobs.length - owned.length
|
|
66347
|
+
};
|
|
66348
|
+
}
|
|
66349
|
+
function normalizeSubscriptionJobs(input) {
|
|
66350
|
+
const seen = /* @__PURE__ */ new Set();
|
|
66351
|
+
const normalized = [];
|
|
66352
|
+
for (const job of input.jobs) {
|
|
66353
|
+
const dedupKey = `${job.jobId}|${job.userAgentId}|${job.aspAgentId}`;
|
|
66354
|
+
if (seen.has(dedupKey)) {
|
|
66355
|
+
continue;
|
|
66356
|
+
}
|
|
66357
|
+
seen.add(dedupKey);
|
|
66358
|
+
normalized.push({
|
|
66359
|
+
jobId: job.jobId,
|
|
66360
|
+
userAgentId: job.userAgentId,
|
|
66361
|
+
aspAgentId: job.aspAgentId,
|
|
66362
|
+
msgType: SUBSCRIPTION_MESSAGE_TYPE,
|
|
66363
|
+
content: input.envelope.content,
|
|
66364
|
+
...input.envelope.deliveryId ? { deliveryId: input.envelope.deliveryId } : {},
|
|
66365
|
+
conversationId: input.conversationId,
|
|
66366
|
+
senderInboxId: input.senderInboxId
|
|
66367
|
+
});
|
|
66368
|
+
}
|
|
66369
|
+
return normalized;
|
|
66370
|
+
}
|
|
66371
|
+
function subscriptionIdempotencyKey(input) {
|
|
66372
|
+
const messageDimension = input.deliveryId || input.messageId;
|
|
66373
|
+
return `${input.myXmtpAddress}|${messageDimension}|${input.jobId}`;
|
|
66374
|
+
}
|
|
66375
|
+
var SUBSCRIPTION_TARGETS_MAX = 2e3;
|
|
66376
|
+
var subscriptionTargets = /* @__PURE__ */ new Map();
|
|
66377
|
+
function tryMarkSubscriptionTarget(key) {
|
|
66378
|
+
if (subscriptionTargets.has(key)) {
|
|
66379
|
+
return false;
|
|
66380
|
+
}
|
|
66381
|
+
subscriptionTargets.set(key, Date.now());
|
|
66382
|
+
while (subscriptionTargets.size > SUBSCRIPTION_TARGETS_MAX) {
|
|
66383
|
+
const oldest = subscriptionTargets.keys().next().value;
|
|
66384
|
+
if (oldest === void 0) {
|
|
66385
|
+
break;
|
|
66386
|
+
}
|
|
66387
|
+
subscriptionTargets.delete(oldest);
|
|
66388
|
+
}
|
|
66389
|
+
return true;
|
|
66390
|
+
}
|
|
66391
|
+
function resetSubscriptionTargetsForTests() {
|
|
66392
|
+
subscriptionTargets.clear();
|
|
66393
|
+
}
|
|
66394
|
+
var SUBSCRIPTION_FANOUT_MAX = 250;
|
|
66395
|
+
function redactSenderInboxId(senderInboxId, left = 8, right = 6) {
|
|
66396
|
+
if (!senderInboxId) {
|
|
66397
|
+
return "(none)";
|
|
66398
|
+
}
|
|
66399
|
+
if (senderInboxId.length <= left + right + 1) {
|
|
66400
|
+
return senderInboxId;
|
|
66401
|
+
}
|
|
66402
|
+
return `${senderInboxId.slice(0, left)}\u2026${senderInboxId.slice(-right)}`;
|
|
66403
|
+
}
|
|
66404
|
+
async function fanOutSubscriptionJobs(input) {
|
|
66405
|
+
const { jobs, myXmtpAddress, messageId, dispatch, concurrency } = input;
|
|
66406
|
+
const total = jobs.length;
|
|
66407
|
+
const capacityAnomaly = total > SUBSCRIPTION_FANOUT_MAX;
|
|
66408
|
+
if (capacityAnomaly) {
|
|
66409
|
+
logWithTimestamp(
|
|
66410
|
+
`[okx-agent-task:${myXmtpAddress}] subscription fan-out capacity anomaly: jobs=${total} max=${SUBSCRIPTION_FANOUT_MAX} message=${messageId}`
|
|
66411
|
+
);
|
|
66412
|
+
}
|
|
66413
|
+
const settled = await parallelMap(
|
|
66414
|
+
jobs,
|
|
66415
|
+
async (job) => {
|
|
66416
|
+
const idempotencyKey = subscriptionIdempotencyKey({
|
|
66417
|
+
myXmtpAddress,
|
|
66418
|
+
deliveryId: job.deliveryId,
|
|
66419
|
+
messageId,
|
|
66420
|
+
jobId: job.jobId
|
|
66421
|
+
});
|
|
66422
|
+
if (subscriptionTargets.has(idempotencyKey)) {
|
|
66423
|
+
return { key: idempotencyKey, outcome: "duplicate" };
|
|
66424
|
+
}
|
|
66425
|
+
const dispatchOutcome = await dispatch(job, idempotencyKey);
|
|
66426
|
+
const isDurableDuplicate = !!dispatchOutcome && dispatchOutcome.created === false;
|
|
66427
|
+
return { key: idempotencyKey, outcome: isDurableDuplicate ? "duplicate" : "started" };
|
|
66428
|
+
},
|
|
66429
|
+
concurrency ?? 20
|
|
66430
|
+
);
|
|
66431
|
+
let started = 0;
|
|
66432
|
+
let failed = 0;
|
|
66433
|
+
let skippedDuplicate = 0;
|
|
66434
|
+
const results = [];
|
|
66435
|
+
settled.forEach((result, idx) => {
|
|
66436
|
+
const job = jobs[idx];
|
|
66437
|
+
if (result.status === "rejected") {
|
|
66438
|
+
failed += 1;
|
|
66439
|
+
results.push({ jobId: job?.jobId ?? "(unknown)", outcome: "failed", error: result.reason });
|
|
66440
|
+
logWithTimestamp(
|
|
66441
|
+
`[okx-agent-task:${myXmtpAddress}] subscription dispatch failed message=${messageId} job=${job?.jobId ?? "(unknown)"} sender=${redactSenderInboxId(job?.senderInboxId)}:`,
|
|
66442
|
+
result.reason
|
|
66443
|
+
);
|
|
66444
|
+
return;
|
|
66445
|
+
}
|
|
66446
|
+
tryMarkSubscriptionTarget(result.value.key);
|
|
66447
|
+
if (result.value.outcome === "duplicate") {
|
|
66448
|
+
skippedDuplicate += 1;
|
|
66449
|
+
results.push({ jobId: job?.jobId ?? "(unknown)", outcome: "duplicate" });
|
|
66450
|
+
} else {
|
|
66451
|
+
started += 1;
|
|
66452
|
+
results.push({ jobId: job?.jobId ?? "(unknown)", outcome: "started" });
|
|
66453
|
+
}
|
|
66454
|
+
});
|
|
66455
|
+
return { total, started, failed, skippedDuplicate, capacityAnomaly, results };
|
|
66456
|
+
}
|
|
66457
|
+
|
|
66458
|
+
// ../core/src/xmtp-sdk/onchainos/list-jobs-by-verified-sender.ts
|
|
66459
|
+
init_log();
|
|
66460
|
+
init_sentry_logger();
|
|
66461
|
+
function isPlainObject4(value) {
|
|
66462
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
66463
|
+
}
|
|
66464
|
+
function isNonEmptyString2(value) {
|
|
66465
|
+
return typeof value === "string" && value.length > 0;
|
|
66466
|
+
}
|
|
66467
|
+
function redactLogValue(value, left = 6, right = 4) {
|
|
66468
|
+
if (!value) {
|
|
66469
|
+
return "(none)";
|
|
66470
|
+
}
|
|
66471
|
+
if (value.length <= left + right + 1) {
|
|
66472
|
+
return "(redacted)";
|
|
66473
|
+
}
|
|
66474
|
+
return `${value.slice(0, left)}\u2026${value.slice(-right)}`;
|
|
66475
|
+
}
|
|
66476
|
+
function guardSessionExpired3(stdout, command) {
|
|
66477
|
+
if (isSessionExpired(stdout)) {
|
|
66478
|
+
reportSessionExpired(command);
|
|
66479
|
+
}
|
|
66480
|
+
}
|
|
66481
|
+
function guardCatchSessionExpired3(err, command) {
|
|
66482
|
+
const stdout = String(err?.stdout ?? "");
|
|
66483
|
+
if (stdout && isSessionExpired(stdout)) {
|
|
66484
|
+
reportSessionExpired(command);
|
|
66485
|
+
}
|
|
66486
|
+
}
|
|
66487
|
+
function buildListJobsByVerifiedSenderArgs(params) {
|
|
66488
|
+
return [
|
|
66489
|
+
"agent",
|
|
66490
|
+
"list-jobs-by-verified-sender",
|
|
66491
|
+
"--group-id",
|
|
66492
|
+
params.groupId,
|
|
66493
|
+
"--sender-inbox-id",
|
|
66494
|
+
params.senderInboxId,
|
|
66495
|
+
"--agentic-id",
|
|
66496
|
+
params.agenticId
|
|
66497
|
+
];
|
|
66498
|
+
}
|
|
66499
|
+
var KNOWN_ERROR_CODES2 = {
|
|
66500
|
+
"130100079": "sender_not_authorized",
|
|
66501
|
+
"130100073": "sender_not_eligible"
|
|
66502
|
+
};
|
|
66503
|
+
function extractErrorText(errorLike) {
|
|
66504
|
+
if (typeof errorLike === "string") {
|
|
66505
|
+
return errorLike;
|
|
66506
|
+
}
|
|
66507
|
+
if (typeof errorLike === "number") {
|
|
66508
|
+
return String(errorLike);
|
|
66509
|
+
}
|
|
66510
|
+
if (errorLike && typeof errorLike === "object") {
|
|
66511
|
+
const anyErr = errorLike;
|
|
66512
|
+
return [anyErr.code, anyErr.message, anyErr.stdout, anyErr.stderr].filter((value) => typeof value === "string" || typeof value === "number").map(String).join(" ");
|
|
66513
|
+
}
|
|
66514
|
+
return errorLike == null ? "" : String(errorLike);
|
|
66515
|
+
}
|
|
66516
|
+
function classifyListJobsError(errorLike) {
|
|
66517
|
+
const text = extractErrorText(errorLike);
|
|
66518
|
+
for (const [code, reason] of Object.entries(KNOWN_ERROR_CODES2)) {
|
|
66519
|
+
if (text.includes(code)) {
|
|
66520
|
+
return { reason, errorCode: code };
|
|
66521
|
+
}
|
|
66522
|
+
}
|
|
66523
|
+
if (/\b401\b/.test(text)) {
|
|
66524
|
+
return { reason: "auth_error", errorCode: "401" };
|
|
66525
|
+
}
|
|
66526
|
+
if (/\b403\b/.test(text)) {
|
|
66527
|
+
return { reason: "auth_error", errorCode: "403" };
|
|
66528
|
+
}
|
|
66529
|
+
return { reason: "invalid_response" };
|
|
66530
|
+
}
|
|
66531
|
+
function normalizeListJobsResponse(data) {
|
|
66532
|
+
const rawJobs = isPlainObject4(data) && Array.isArray(data.jobs) ? data.jobs : [];
|
|
66533
|
+
const seen = /* @__PURE__ */ new Set();
|
|
66534
|
+
const jobs = [];
|
|
66535
|
+
let invalidCount = 0;
|
|
66536
|
+
for (const item of rawJobs) {
|
|
66537
|
+
if (!isPlainObject4(item) || !isNonEmptyString2(item.jobId) || !isNonEmptyString2(item.userAgentId) || !isNonEmptyString2(item.aspAgentId)) {
|
|
66538
|
+
invalidCount += 1;
|
|
66539
|
+
continue;
|
|
66540
|
+
}
|
|
66541
|
+
const key = `${item.jobId}|${item.userAgentId}|${item.aspAgentId}`;
|
|
66542
|
+
if (seen.has(key)) {
|
|
66543
|
+
continue;
|
|
66544
|
+
}
|
|
66545
|
+
seen.add(key);
|
|
66546
|
+
jobs.push({ jobId: item.jobId, userAgentId: item.userAgentId, aspAgentId: item.aspAgentId });
|
|
66547
|
+
}
|
|
66548
|
+
return { jobs, invalidCount };
|
|
66549
|
+
}
|
|
66550
|
+
async function listJobsByVerifiedSender(params, execFn = exec) {
|
|
66551
|
+
logWithTimestamp(
|
|
66552
|
+
`[onchainos] listing jobs by verified sender: group=${params.groupId} sender=${redactLogValue(params.senderInboxId)} agentic=${params.agenticId}`
|
|
66553
|
+
);
|
|
66554
|
+
let stdout;
|
|
66555
|
+
let stderr;
|
|
66556
|
+
try {
|
|
66557
|
+
({ stdout, stderr } = await execFn(buildListJobsByVerifiedSenderArgs(params)));
|
|
66558
|
+
} catch (err) {
|
|
66559
|
+
guardCatchSessionExpired3(err, "list-jobs-by-verified-sender");
|
|
66560
|
+
const classified = classifyListJobsError(err);
|
|
66561
|
+
const reason = classified.reason === "invalid_response" ? "network_error" : classified.reason;
|
|
66562
|
+
warnWithTimestamp(
|
|
66563
|
+
`[onchainos] list-jobs-by-verified-sender exec failed (group=${params.groupId} sender=${redactLogValue(params.senderInboxId)}); fail-closed reason=${reason}`
|
|
66564
|
+
);
|
|
66565
|
+
return { status: "fail_closed", jobs: [], invalidCount: 0, reason, errorCode: classified.errorCode };
|
|
66566
|
+
}
|
|
66567
|
+
if (stderr) {
|
|
66568
|
+
logWithTimestamp(`[onchainos] stderr (list-jobs-by-verified-sender): ${stderr}`);
|
|
66569
|
+
}
|
|
66570
|
+
let res;
|
|
66571
|
+
try {
|
|
66572
|
+
res = parseCliJson(stdout, "list-jobs-by-verified-sender", {
|
|
66573
|
+
groupId: params.groupId,
|
|
66574
|
+
agenticId: params.agenticId
|
|
66575
|
+
});
|
|
66576
|
+
} catch {
|
|
66577
|
+
return { status: "fail_closed", jobs: [], invalidCount: 0, reason: "invalid_response" };
|
|
66578
|
+
}
|
|
66579
|
+
if (!res.ok) {
|
|
66580
|
+
guardSessionExpired3(stdout, "list-jobs-by-verified-sender");
|
|
66581
|
+
const classified = classifyListJobsError(res.error);
|
|
66582
|
+
warnWithTimestamp(
|
|
66583
|
+
`[onchainos] list-jobs-by-verified-sender ok=false (group=${params.groupId}); fail-closed reason=${classified.reason}`
|
|
66584
|
+
);
|
|
66585
|
+
logger.error(
|
|
66586
|
+
LogEvent.ONCHAINOS_CLI_ERROR,
|
|
66587
|
+
new Error("list-jobs-by-verified-sender ok=false"),
|
|
66588
|
+
cliOkFalseExtras(stdout, "list-jobs-by-verified-sender", {
|
|
66589
|
+
groupId: params.groupId,
|
|
66590
|
+
agenticId: params.agenticId,
|
|
66591
|
+
reason: classified.reason
|
|
66592
|
+
})
|
|
66593
|
+
);
|
|
66594
|
+
return { status: "fail_closed", jobs: [], invalidCount: 0, reason: classified.reason, errorCode: classified.errorCode };
|
|
66595
|
+
}
|
|
66596
|
+
const { jobs, invalidCount } = normalizeListJobsResponse(res.data);
|
|
66597
|
+
if (jobs.length === 0) {
|
|
66598
|
+
logWithTimestamp(
|
|
66599
|
+
`[onchainos] list-jobs-by-verified-sender: empty (group=${params.groupId} invalidCount=${invalidCount})`
|
|
66600
|
+
);
|
|
66601
|
+
return { status: "empty", jobs, invalidCount };
|
|
66602
|
+
}
|
|
66603
|
+
logWithTimestamp(
|
|
66604
|
+
`[onchainos] list-jobs-by-verified-sender: ok (group=${params.groupId} jobs=${jobs.length} invalidCount=${invalidCount})`
|
|
66605
|
+
);
|
|
66606
|
+
return { status: "ok", jobs, invalidCount };
|
|
66607
|
+
}
|
|
66608
|
+
var LIST_JOBS_BY_VERIFIED_SENDER_HELP_TOKEN = "list-jobs-by-verified-sender";
|
|
66609
|
+
function listJobsByVerifiedSenderHelpAdvertisesCommand(helpText) {
|
|
66610
|
+
if (typeof helpText !== "string" || helpText.length === 0) {
|
|
66611
|
+
return false;
|
|
66612
|
+
}
|
|
66613
|
+
const lower = helpText.toLowerCase();
|
|
66614
|
+
if (/unknown command|unrecognized|not a valid command|no such (sub)?command|command not found/.test(lower)) {
|
|
66615
|
+
return false;
|
|
66616
|
+
}
|
|
66617
|
+
return lower.includes(LIST_JOBS_BY_VERIFIED_SENDER_HELP_TOKEN);
|
|
66618
|
+
}
|
|
66619
|
+
var CAPABILITY_UPGRADE_PAIR_KEY = "onchainos:list-jobs-by-verified-sender";
|
|
66620
|
+
var CAPABILITY_UPGRADE_REASON = "OnchainOS does not support `agent list-jobs-by-verified-sender`; the V2 subscription shared-group inbound path is fail-closed until OnchainOS is upgraded. Upgrade the OnchainOS CLI, then re-run.";
|
|
66621
|
+
var capabilityProbe2 = null;
|
|
66622
|
+
var capabilityRecommendedPairs = /* @__PURE__ */ new Set();
|
|
66623
|
+
function resetListJobsByVerifiedSenderCapabilityForTests() {
|
|
66624
|
+
capabilityProbe2 = null;
|
|
66625
|
+
capabilityRecommendedPairs.clear();
|
|
66626
|
+
}
|
|
66627
|
+
function maybeRecommendListJobsUpgrade(capability) {
|
|
66628
|
+
if (capability.supported || capabilityRecommendedPairs.has(CAPABILITY_UPGRADE_PAIR_KEY)) {
|
|
66629
|
+
return;
|
|
66630
|
+
}
|
|
66631
|
+
warnWithTimestamp(
|
|
66632
|
+
`[onchainos] list-jobs-by-verified-sender unsupported (reason=${capability.reason}); ${CAPABILITY_UPGRADE_REASON}`
|
|
66633
|
+
);
|
|
66634
|
+
const hook = XmtpService.getInstance().tools?.notifyUpgradeRecommendation;
|
|
66635
|
+
if (!hook) {
|
|
66636
|
+
return;
|
|
66637
|
+
}
|
|
66638
|
+
capabilityRecommendedPairs.add(CAPABILITY_UPGRADE_PAIR_KEY);
|
|
66639
|
+
try {
|
|
66640
|
+
void Promise.resolve(
|
|
66641
|
+
hook({
|
|
66642
|
+
component: "onchainos",
|
|
66643
|
+
capability: LIST_JOBS_BY_VERIFIED_SENDER_HELP_TOKEN,
|
|
66644
|
+
reason: CAPABILITY_UPGRADE_REASON
|
|
66645
|
+
})
|
|
66646
|
+
).catch((err) => {
|
|
66647
|
+
warnWithTimestamp("[onchainos] list-jobs-by-verified-sender upgrade notice async delivery failed:", err);
|
|
66648
|
+
});
|
|
66649
|
+
} catch (err) {
|
|
66650
|
+
warnWithTimestamp("[onchainos] list-jobs-by-verified-sender upgrade notice threw:", err);
|
|
66651
|
+
}
|
|
66652
|
+
}
|
|
66653
|
+
function detectListJobsByVerifiedSenderSupport(execFn = exec) {
|
|
66654
|
+
if (!capabilityProbe2) {
|
|
66655
|
+
capabilityProbe2 = (async () => {
|
|
66656
|
+
try {
|
|
66657
|
+
const { stdout, stderr } = await execFn([
|
|
66658
|
+
"agent",
|
|
66659
|
+
"list-jobs-by-verified-sender",
|
|
66660
|
+
"--help"
|
|
66661
|
+
]);
|
|
66662
|
+
const supported = listJobsByVerifiedSenderHelpAdvertisesCommand(`${stdout}
|
|
66663
|
+
${stderr}`);
|
|
66664
|
+
logWithTimestamp(
|
|
66665
|
+
`[onchainos] list-jobs-by-verified-sender capability: ${supported ? "supported" : "unsupported_cli_capability"}`
|
|
66666
|
+
);
|
|
66667
|
+
return supported ? { supported: true } : { supported: false, reason: "unsupported_cli_capability" };
|
|
66668
|
+
} catch (err) {
|
|
66669
|
+
logWithTimestamp(
|
|
66670
|
+
"[onchainos] list-jobs-by-verified-sender --help probe failed; treating as onchainos_upgrade_required:",
|
|
66671
|
+
err
|
|
66672
|
+
);
|
|
66673
|
+
return { supported: false, reason: "onchainos_upgrade_required" };
|
|
66674
|
+
}
|
|
66675
|
+
})().then((capability) => {
|
|
66676
|
+
maybeRecommendListJobsUpgrade(capability);
|
|
66677
|
+
return capability;
|
|
66678
|
+
});
|
|
66679
|
+
}
|
|
66680
|
+
return capabilityProbe2;
|
|
66681
|
+
}
|
|
66682
|
+
async function listJobsByVerifiedSenderWithCapability(params, execFn = exec) {
|
|
66683
|
+
const capability = await detectListJobsByVerifiedSenderSupport(execFn);
|
|
66684
|
+
if (!capability.supported) {
|
|
66685
|
+
warnWithTimestamp(
|
|
66686
|
+
`[onchainos] list-jobs-by-verified-sender skipped: CLI capability unavailable (reason=${capability.reason}) group=${params.groupId} sender=${redactLogValue(params.senderInboxId)}`
|
|
66687
|
+
);
|
|
66688
|
+
return { status: "fail_closed", jobs: [], invalidCount: 0, reason: capability.reason };
|
|
66689
|
+
}
|
|
66690
|
+
return listJobsByVerifiedSender(params, execFn);
|
|
66691
|
+
}
|
|
66692
|
+
|
|
66693
|
+
// src/message-handler.ts
|
|
65727
66694
|
var PROCESSED_IDS_MAX = 1e3;
|
|
65728
66695
|
var processedMessageIds = /* @__PURE__ */ new Map();
|
|
65729
66696
|
function tryMarkProcessed(messageId) {
|
|
@@ -65740,7 +66707,7 @@ function tryMarkProcessed(messageId) {
|
|
|
65740
66707
|
}
|
|
65741
66708
|
return true;
|
|
65742
66709
|
}
|
|
65743
|
-
function
|
|
66710
|
+
function isPlainObject5(value) {
|
|
65744
66711
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
65745
66712
|
}
|
|
65746
66713
|
function safeStringify(value) {
|
|
@@ -65801,9 +66768,9 @@ function readNumber(value) {
|
|
|
65801
66768
|
}
|
|
65802
66769
|
function resolveSessionAgentId(params) {
|
|
65803
66770
|
const { chatType, payload, myXmtpAddress } = params;
|
|
65804
|
-
const payloadObject =
|
|
65805
|
-
const sender =
|
|
65806
|
-
const message =
|
|
66771
|
+
const payloadObject = isPlainObject5(payload) ? payload : null;
|
|
66772
|
+
const sender = isPlainObject5(payloadObject?.sender) ? payloadObject.sender : null;
|
|
66773
|
+
const message = isPlainObject5(payloadObject?.message) ? payloadObject.message : null;
|
|
65807
66774
|
const localAgentId = XmtpService.getInstance().getAgentByAddress(myXmtpAddress)?.agentId ?? null;
|
|
65808
66775
|
if (chatType === "group") {
|
|
65809
66776
|
return readString3(sender?.agentId) ?? readString3(payloadObject?.receiverAgentId) ?? localAgentId;
|
|
@@ -65814,7 +66781,7 @@ function resolveSessionAgentId(params) {
|
|
|
65814
66781
|
return localAgentId;
|
|
65815
66782
|
}
|
|
65816
66783
|
function routeMessage(chatType, parsed, payload) {
|
|
65817
|
-
if (!parsed || !
|
|
66784
|
+
if (!parsed || !isPlainObject5(payload)) {
|
|
65818
66785
|
return {
|
|
65819
66786
|
jobId: BACKUP_JOB_ID,
|
|
65820
66787
|
route: "backup",
|
|
@@ -65826,7 +66793,7 @@ function routeMessage(chatType, parsed, payload) {
|
|
|
65826
66793
|
return jobId ? { jobId, route: "job", routeReason: "group-job-id" } : { jobId: BACKUP_JOB_ID, route: "backup", routeReason: "group-missing-job-id" };
|
|
65827
66794
|
}
|
|
65828
66795
|
if (chatType === "dm") {
|
|
65829
|
-
const message =
|
|
66796
|
+
const message = isPlainObject5(payload.message) ? payload.message : null;
|
|
65830
66797
|
const nestedJobId = readString3(message?.jobId);
|
|
65831
66798
|
const directJobId = readString3(payload.jobId);
|
|
65832
66799
|
const jobId = nestedJobId ?? directJobId;
|
|
@@ -65839,10 +66806,10 @@ function routeMessage(chatType, parsed, payload) {
|
|
|
65839
66806
|
return { jobId: BACKUP_JOB_ID, route: "backup", routeReason: "unknown-conversation" };
|
|
65840
66807
|
}
|
|
65841
66808
|
function extractDirectToUserNotification(payload) {
|
|
65842
|
-
if (!
|
|
66809
|
+
if (!isPlainObject5(payload)) {
|
|
65843
66810
|
return { kind: "none" };
|
|
65844
66811
|
}
|
|
65845
|
-
const message =
|
|
66812
|
+
const message = isPlainObject5(payload.message) ? payload.message : null;
|
|
65846
66813
|
if (message?.isDirectToUser !== true) {
|
|
65847
66814
|
return { kind: "none" };
|
|
65848
66815
|
}
|
|
@@ -65866,10 +66833,10 @@ function extractDirectToUserNotification(payload) {
|
|
|
65866
66833
|
};
|
|
65867
66834
|
}
|
|
65868
66835
|
function extractSystemNotification(payload) {
|
|
65869
|
-
if (!
|
|
66836
|
+
if (!isPlainObject5(payload)) {
|
|
65870
66837
|
return null;
|
|
65871
66838
|
}
|
|
65872
|
-
const message =
|
|
66839
|
+
const message = isPlainObject5(payload.message) ? payload.message : null;
|
|
65873
66840
|
const isDirectCommunication = message?.isDirectCommunication === true;
|
|
65874
66841
|
if (message?.source !== "system" && !isDirectCommunication) {
|
|
65875
66842
|
return null;
|
|
@@ -66104,7 +67071,7 @@ function inboundStageExtras(stage, outcome) {
|
|
|
66104
67071
|
})
|
|
66105
67072
|
};
|
|
66106
67073
|
}
|
|
66107
|
-
function
|
|
67074
|
+
function definedExtras2(input) {
|
|
66108
67075
|
return Object.entries(input).reduce((out, [key, value]) => {
|
|
66109
67076
|
const text = readString3(value);
|
|
66110
67077
|
if (text) {
|
|
@@ -66136,7 +67103,7 @@ function buildInboundTerminalExtras(input) {
|
|
|
66136
67103
|
originPlatform: classifyOriginPlatform({ env: process.env }),
|
|
66137
67104
|
deliveryId: resolveDeliveryId({ messageId, jobId, sessionKey })
|
|
66138
67105
|
}),
|
|
66139
|
-
...
|
|
67106
|
+
...definedExtras2({
|
|
66140
67107
|
messageId,
|
|
66141
67108
|
conversationId,
|
|
66142
67109
|
chatType,
|
|
@@ -66170,7 +67137,7 @@ function maybeNotifyInboundAgentMessage(params) {
|
|
|
66170
67137
|
return;
|
|
66171
67138
|
}
|
|
66172
67139
|
const content = payloadObject.content;
|
|
66173
|
-
const sender =
|
|
67140
|
+
const sender = isPlainObject5(payloadObject.sender) ? payloadObject.sender : null;
|
|
66174
67141
|
const localAgent = XmtpService.getInstance().getAgentByAddress(params.deps.myXmtpAddress);
|
|
66175
67142
|
void notifyAgentMessageToUserAttention({
|
|
66176
67143
|
direction: "inbound" /* INBOUND */,
|
|
@@ -66201,11 +67168,11 @@ function stringifySystemPayload(payload) {
|
|
|
66201
67168
|
}
|
|
66202
67169
|
}
|
|
66203
67170
|
function summarizePayloadForLog(payload) {
|
|
66204
|
-
if (!
|
|
67171
|
+
if (!isPlainObject5(payload)) {
|
|
66205
67172
|
return "payload=non-object";
|
|
66206
67173
|
}
|
|
66207
|
-
const message =
|
|
66208
|
-
const sender =
|
|
67174
|
+
const message = isPlainObject5(payload.message) ? payload.message : null;
|
|
67175
|
+
const sender = isPlainObject5(payload.sender) ? payload.sender : null;
|
|
66209
67176
|
const jobId = readString3(payload.jobId) ?? readString3(message?.jobId);
|
|
66210
67177
|
const parts = [
|
|
66211
67178
|
readString3(payload.msgType) ? `type=${readString3(payload.msgType)}` : null,
|
|
@@ -66474,7 +67441,7 @@ async function verifyInboundA2AGroupMessage(params) {
|
|
|
66474
67441
|
messageId,
|
|
66475
67442
|
groupId,
|
|
66476
67443
|
jobId,
|
|
66477
|
-
agentId: readString3(
|
|
67444
|
+
agentId: readString3(isPlainObject5(payload.sender) ? payload.sender.agentId : null),
|
|
66478
67445
|
localAgentId: myAgent?.agentId ?? null,
|
|
66479
67446
|
senderAddress,
|
|
66480
67447
|
senderInboxId,
|
|
@@ -66500,7 +67467,7 @@ async function verifyInboundA2AGroupMessage(params) {
|
|
|
66500
67467
|
});
|
|
66501
67468
|
return false;
|
|
66502
67469
|
}
|
|
66503
|
-
const sender =
|
|
67470
|
+
const sender = isPlainObject5(payload.sender) ? payload.sender : null;
|
|
66504
67471
|
const senderAgentId = readString3(sender?.agentId);
|
|
66505
67472
|
const senderRole = readNumber(sender?.role);
|
|
66506
67473
|
if (!senderAgentId || !myAgent) {
|
|
@@ -66669,9 +67636,302 @@ ${failureMessage}`,
|
|
|
66669
67636
|
}
|
|
66670
67637
|
return true;
|
|
66671
67638
|
}
|
|
67639
|
+
async function processSubscriptionInbound(ctx, deps, input) {
|
|
67640
|
+
const { decision, conversationId, messageId } = input;
|
|
67641
|
+
const senderInboxId = ctx.message.senderInboxId ?? "";
|
|
67642
|
+
if (decision.kind === "drop") {
|
|
67643
|
+
logger.info(
|
|
67644
|
+
LogEvent.SUBSCRIPTION_INBOUND_GATE_DROPPED,
|
|
67645
|
+
buildSubscriptionInboundExtras({
|
|
67646
|
+
checkpoint: "inbound/subscription_gate_dropped",
|
|
67647
|
+
outcome: "dropped",
|
|
67648
|
+
conversationId,
|
|
67649
|
+
messageId,
|
|
67650
|
+
senderInboxId: shortenLogValue(senderInboxId),
|
|
67651
|
+
reason: decision.reason
|
|
67652
|
+
})
|
|
67653
|
+
);
|
|
67654
|
+
logWithTimestamp(
|
|
67655
|
+
`[okx-agent-task:${deps.myXmtpAddress}] subscription message dropped reason=${decision.reason}${decision.detail ? ` detail=${decision.detail}` : ""} conv=${conversationId} message=${shortenLogValue(messageId)} sender=${shortenLogValue(senderInboxId)}`
|
|
67656
|
+
);
|
|
67657
|
+
return true;
|
|
67658
|
+
}
|
|
67659
|
+
if (decision.kind === "not_subscription") {
|
|
67660
|
+
return true;
|
|
67661
|
+
}
|
|
67662
|
+
const { envelope } = decision;
|
|
67663
|
+
const agenticId = XmtpService.getInstance().getAgentByAddress(deps.myXmtpAddress)?.agentId;
|
|
67664
|
+
if (!agenticId) {
|
|
67665
|
+
logWithTimestamp(
|
|
67666
|
+
`[okx-agent-task:${deps.myXmtpAddress}] subscription fail-closed: no local agenticId for ${deps.myXmtpAddress}, conv=${conversationId} message=${shortenLogValue(messageId)}`
|
|
67667
|
+
);
|
|
67668
|
+
logger.error(
|
|
67669
|
+
LogEvent.SUBSCRIPTION_INBOUND_AGENTIC_ID_MISSING,
|
|
67670
|
+
new Error("Subscription inbound: local agenticId not resolved"),
|
|
67671
|
+
buildSubscriptionInboundExtras({
|
|
67672
|
+
checkpoint: "inbound/subscription_agentic_id",
|
|
67673
|
+
outcome: "blocked",
|
|
67674
|
+
conversationId,
|
|
67675
|
+
messageId,
|
|
67676
|
+
senderInboxId: shortenLogValue(senderInboxId),
|
|
67677
|
+
reason: "missing_agentic_id"
|
|
67678
|
+
})
|
|
67679
|
+
);
|
|
67680
|
+
return true;
|
|
67681
|
+
}
|
|
67682
|
+
logWithTimestamp(
|
|
67683
|
+
`[okx-agent-task:${deps.myXmtpAddress}] subscription received msgType=${envelope.msgType} conv=${conversationId} message=${shortenLogValue(messageId)} sender=${shortenLogValue(senderInboxId)}`
|
|
67684
|
+
);
|
|
67685
|
+
logger.info(
|
|
67686
|
+
LogEvent.SUBSCRIPTION_INBOUND_RECEIVED,
|
|
67687
|
+
buildSubscriptionInboundExtras({
|
|
67688
|
+
checkpoint: "inbound/subscription_received",
|
|
67689
|
+
userAgentId: agenticId,
|
|
67690
|
+
conversationId,
|
|
67691
|
+
messageId,
|
|
67692
|
+
deliveryId: envelope.deliveryId,
|
|
67693
|
+
senderInboxId: shortenLogValue(senderInboxId)
|
|
67694
|
+
})
|
|
67695
|
+
);
|
|
67696
|
+
const listJobs = deps.listJobsByVerifiedSenderImpl ?? listJobsByVerifiedSenderWithCapability;
|
|
67697
|
+
logger.info(
|
|
67698
|
+
LogEvent.SUBSCRIPTION_JOBS_QUERY_STARTED,
|
|
67699
|
+
buildSubscriptionInboundExtras({
|
|
67700
|
+
checkpoint: "inbound/subscription_jobs_query_started",
|
|
67701
|
+
userAgentId: agenticId,
|
|
67702
|
+
conversationId,
|
|
67703
|
+
messageId
|
|
67704
|
+
})
|
|
67705
|
+
);
|
|
67706
|
+
const listJobsResult = await listJobs({
|
|
67707
|
+
groupId: conversationId,
|
|
67708
|
+
senderInboxId,
|
|
67709
|
+
agenticId
|
|
67710
|
+
});
|
|
67711
|
+
logWithTimestamp(
|
|
67712
|
+
`[okx-agent-task:${deps.myXmtpAddress}] subscription queried status=${listJobsResult.status} jobs=${listJobsResult.jobs.length} invalid=${listJobsResult.invalidCount} conv=${conversationId} message=${shortenLogValue(messageId)}`
|
|
67713
|
+
);
|
|
67714
|
+
if (listJobsResult.status === "fail_closed") {
|
|
67715
|
+
logger.error(
|
|
67716
|
+
LogEvent.SUBSCRIPTION_JOBS_FAIL_CLOSED,
|
|
67717
|
+
new Error("Subscription inbound: listJobsByVerifiedSender fail-closed"),
|
|
67718
|
+
buildSubscriptionInboundExtras({
|
|
67719
|
+
checkpoint: "inbound/subscription_jobs_fail_closed",
|
|
67720
|
+
outcome: "blocked",
|
|
67721
|
+
userAgentId: agenticId,
|
|
67722
|
+
conversationId,
|
|
67723
|
+
messageId,
|
|
67724
|
+
senderInboxId: shortenLogValue(senderInboxId),
|
|
67725
|
+
reason: listJobsResult.reason ?? "unknown",
|
|
67726
|
+
errorCode: listJobsResult.errorCode
|
|
67727
|
+
})
|
|
67728
|
+
);
|
|
67729
|
+
return true;
|
|
67730
|
+
}
|
|
67731
|
+
if (listJobsResult.status === "empty") {
|
|
67732
|
+
logWithTimestamp(
|
|
67733
|
+
`[okx-agent-task:${deps.myXmtpAddress}] subscription empty: no verified jobs for conv=${conversationId} message=${shortenLogValue(messageId)}`
|
|
67734
|
+
);
|
|
67735
|
+
logger.info(
|
|
67736
|
+
LogEvent.SUBSCRIPTION_JOBS_EMPTY,
|
|
67737
|
+
buildSubscriptionInboundExtras({
|
|
67738
|
+
checkpoint: "inbound/subscription_jobs_empty",
|
|
67739
|
+
outcome: "ignored",
|
|
67740
|
+
userAgentId: agenticId,
|
|
67741
|
+
conversationId,
|
|
67742
|
+
messageId,
|
|
67743
|
+
reason: "jobs_empty",
|
|
67744
|
+
returnedCount: 0,
|
|
67745
|
+
invalidCount: listJobsResult.invalidCount
|
|
67746
|
+
})
|
|
67747
|
+
);
|
|
67748
|
+
return true;
|
|
67749
|
+
}
|
|
67750
|
+
logger.info(
|
|
67751
|
+
LogEvent.SUBSCRIPTION_JOBS_QUERY_SUCCEEDED,
|
|
67752
|
+
buildSubscriptionInboundExtras({
|
|
67753
|
+
checkpoint: "inbound/subscription_jobs_query_succeeded",
|
|
67754
|
+
userAgentId: agenticId,
|
|
67755
|
+
conversationId,
|
|
67756
|
+
messageId,
|
|
67757
|
+
returnedCount: listJobsResult.jobs.length,
|
|
67758
|
+
invalidCount: listJobsResult.invalidCount
|
|
67759
|
+
})
|
|
67760
|
+
);
|
|
67761
|
+
const ownership = partitionSubscriptionJobsByOwner({
|
|
67762
|
+
jobs: listJobsResult.jobs,
|
|
67763
|
+
localAgentId: agenticId
|
|
67764
|
+
});
|
|
67765
|
+
logWithTimestamp(
|
|
67766
|
+
`[okx-agent-task:${deps.myXmtpAddress}] subscription routed receiver=${agenticId} returned=${ownership.returnedCount} localOwned=${ownership.ownedCount} ignored=${ownership.ignoredCount} conv=${conversationId} message=${shortenLogValue(messageId)}`
|
|
67767
|
+
);
|
|
67768
|
+
logger.info(
|
|
67769
|
+
LogEvent.SUBSCRIPTION_INBOUND_OWNERSHIP_ROUTED,
|
|
67770
|
+
buildSubscriptionInboundExtras({
|
|
67771
|
+
checkpoint: "inbound/subscription_ownership_routed",
|
|
67772
|
+
outcome: ownership.ownedCount === 0 ? "ignored" : null,
|
|
67773
|
+
userAgentId: agenticId,
|
|
67774
|
+
conversationId,
|
|
67775
|
+
messageId,
|
|
67776
|
+
returnedCount: ownership.returnedCount,
|
|
67777
|
+
ownedCount: ownership.ownedCount,
|
|
67778
|
+
ignoredCount: ownership.ignoredCount
|
|
67779
|
+
})
|
|
67780
|
+
);
|
|
67781
|
+
if (ownership.ownedCount === 0) {
|
|
67782
|
+
return true;
|
|
67783
|
+
}
|
|
67784
|
+
const normalizedJobs = normalizeSubscriptionJobs({
|
|
67785
|
+
jobs: ownership.owned,
|
|
67786
|
+
envelope,
|
|
67787
|
+
conversationId,
|
|
67788
|
+
senderInboxId
|
|
67789
|
+
});
|
|
67790
|
+
logWithTimestamp(
|
|
67791
|
+
`[okx-agent-task:${deps.myXmtpAddress}] subscription expanded jobs=${normalizedJobs.length} conv=${conversationId} message=${shortenLogValue(messageId)}`
|
|
67792
|
+
);
|
|
67793
|
+
let senderXmtpAddress = null;
|
|
67794
|
+
try {
|
|
67795
|
+
const resolved = await ctx.getSenderAddress();
|
|
67796
|
+
senderXmtpAddress = resolved ? resolved : null;
|
|
67797
|
+
} catch (err) {
|
|
67798
|
+
logWithTimestamp(
|
|
67799
|
+
`[okx-agent-task:${deps.myXmtpAddress}] subscription sender address unresolved (degrading to null) conv=${conversationId} message=${shortenLogValue(messageId)}:`,
|
|
67800
|
+
err
|
|
67801
|
+
);
|
|
67802
|
+
}
|
|
67803
|
+
const fanoutResult = await fanOutSubscriptionJobs({
|
|
67804
|
+
jobs: normalizedJobs,
|
|
67805
|
+
myXmtpAddress: deps.myXmtpAddress,
|
|
67806
|
+
messageId,
|
|
67807
|
+
dispatch: async (job, idempotencyKey) => {
|
|
67808
|
+
const sessionKey = buildSessionKey({
|
|
67809
|
+
jobId: job.jobId,
|
|
67810
|
+
myAgentId: job.userAgentId,
|
|
67811
|
+
toAgentId: job.aspAgentId
|
|
67812
|
+
});
|
|
67813
|
+
deps.sessionStore?.upsertSession({
|
|
67814
|
+
sessionKey,
|
|
67815
|
+
jobId: job.jobId,
|
|
67816
|
+
myAgentId: job.userAgentId,
|
|
67817
|
+
toAgentId: job.aspAgentId,
|
|
67818
|
+
groupId: job.conversationId,
|
|
67819
|
+
myAgentXmtpAddress: deps.myXmtpAddress,
|
|
67820
|
+
toAgentXmtpAddress: senderXmtpAddress
|
|
67821
|
+
});
|
|
67822
|
+
return deps.onSessionMessage?.({
|
|
67823
|
+
sessionKey,
|
|
67824
|
+
content: JSON.stringify({
|
|
67825
|
+
msgType: job.msgType,
|
|
67826
|
+
content: job.content,
|
|
67827
|
+
...job.deliveryId ? { deliveryId: job.deliveryId } : {},
|
|
67828
|
+
jobId: job.jobId,
|
|
67829
|
+
userAgentId: job.userAgentId,
|
|
67830
|
+
aspAgentId: job.aspAgentId,
|
|
67831
|
+
conversationId: job.conversationId,
|
|
67832
|
+
senderInboxId: job.senderInboxId,
|
|
67833
|
+
// Raw XMTP messageId preserved for sender/receiver telemetry join;
|
|
67834
|
+
// the durable dedup identity is the idempotencyKey passed as this
|
|
67835
|
+
// session-message's own `messageId` field below (M1 fix).
|
|
67836
|
+
xmtpMessageId: messageId
|
|
67837
|
+
}),
|
|
67838
|
+
messageId: idempotencyKey,
|
|
67839
|
+
// Durable exactly-once enqueue key (M2): the wiring persists via
|
|
67840
|
+
// CommandStore.submitIdempotent keyed on sessionKey+messageId so a
|
|
67841
|
+
// re-processed / replayed message never creates a second command.
|
|
67842
|
+
idempotencyKey,
|
|
67843
|
+
jobId: job.jobId,
|
|
67844
|
+
agentId: job.userAgentId
|
|
67845
|
+
});
|
|
67846
|
+
}
|
|
67847
|
+
});
|
|
67848
|
+
logWithTimestamp(
|
|
67849
|
+
`[okx-agent-task:${deps.myXmtpAddress}] subscription fan-out succeeded=${fanoutResult.started} failed=${fanoutResult.failed} skippedDuplicate=${fanoutResult.skippedDuplicate} total=${fanoutResult.total} capacityAnomaly=${fanoutResult.capacityAnomaly} conv=${conversationId} message=${shortenLogValue(messageId)}`
|
|
67850
|
+
);
|
|
67851
|
+
const normalizedJobsById = new Map(normalizedJobs.map((job) => [job.jobId, job]));
|
|
67852
|
+
for (const result of fanoutResult.results) {
|
|
67853
|
+
const job = normalizedJobsById.get(result.jobId);
|
|
67854
|
+
if (result.outcome === "started") {
|
|
67855
|
+
logger.info(
|
|
67856
|
+
LogEvent.SUBSCRIPTION_JOB_DISPATCHED,
|
|
67857
|
+
buildSubscriptionJobExtras({
|
|
67858
|
+
checkpoint: "dispatch/subscription_job_dispatched",
|
|
67859
|
+
outcome: "success",
|
|
67860
|
+
jobId: result.jobId,
|
|
67861
|
+
userAgentId: agenticId,
|
|
67862
|
+
aspAgentId: job?.aspAgentId,
|
|
67863
|
+
conversationId,
|
|
67864
|
+
deliveryId: envelope.deliveryId
|
|
67865
|
+
})
|
|
67866
|
+
);
|
|
67867
|
+
} else if (result.outcome === "duplicate") {
|
|
67868
|
+
logger.info(
|
|
67869
|
+
LogEvent.SUBSCRIPTION_JOB_DUPLICATE_IGNORED,
|
|
67870
|
+
buildSubscriptionJobExtras({
|
|
67871
|
+
checkpoint: "dispatch/subscription_job_duplicate_ignored",
|
|
67872
|
+
outcome: "ignored",
|
|
67873
|
+
jobId: result.jobId,
|
|
67874
|
+
userAgentId: agenticId,
|
|
67875
|
+
aspAgentId: job?.aspAgentId,
|
|
67876
|
+
conversationId,
|
|
67877
|
+
deliveryId: envelope.deliveryId,
|
|
67878
|
+
reason: "duplicate_delivery"
|
|
67879
|
+
})
|
|
67880
|
+
);
|
|
67881
|
+
} else {
|
|
67882
|
+
logger.error(
|
|
67883
|
+
LogEvent.SUBSCRIPTION_JOB_FAILED,
|
|
67884
|
+
toLoggableError(result.error),
|
|
67885
|
+
buildSubscriptionJobExtras({
|
|
67886
|
+
checkpoint: "dispatch/subscription_job_failed",
|
|
67887
|
+
outcome: "failed",
|
|
67888
|
+
jobId: result.jobId,
|
|
67889
|
+
userAgentId: agenticId,
|
|
67890
|
+
aspAgentId: job?.aspAgentId,
|
|
67891
|
+
conversationId,
|
|
67892
|
+
deliveryId: envelope.deliveryId,
|
|
67893
|
+
reason: "session_dispatch_failed"
|
|
67894
|
+
})
|
|
67895
|
+
);
|
|
67896
|
+
}
|
|
67897
|
+
}
|
|
67898
|
+
logger.info(
|
|
67899
|
+
LogEvent.SUBSCRIPTION_FANOUT_SUMMARY,
|
|
67900
|
+
buildSubscriptionJobExtras({
|
|
67901
|
+
checkpoint: "dispatch/subscription_fanout_summary",
|
|
67902
|
+
outcome: fanoutResult.failed === 0 ? "success" : fanoutResult.started > 0 || fanoutResult.skippedDuplicate > 0 ? "partial" : "failed",
|
|
67903
|
+
conversationId,
|
|
67904
|
+
userAgentId: agenticId,
|
|
67905
|
+
total: fanoutResult.total,
|
|
67906
|
+
started: fanoutResult.started,
|
|
67907
|
+
failed: fanoutResult.failed,
|
|
67908
|
+
skippedDuplicate: fanoutResult.skippedDuplicate
|
|
67909
|
+
})
|
|
67910
|
+
);
|
|
67911
|
+
return true;
|
|
67912
|
+
}
|
|
66672
67913
|
async function processFileMessage(ctx, deps, options = {}) {
|
|
66673
67914
|
const messageId = ctx.message.id ?? "";
|
|
66674
67915
|
const timing = createInboundTimingTracker(extractXmtpSentAtMs2(ctx.message));
|
|
67916
|
+
const subscriptionPrecheckRawText = extractRawText(ctx.message.content);
|
|
67917
|
+
const subscriptionPrecheckParse = parseJson2(subscriptionPrecheckRawText);
|
|
67918
|
+
if (subscriptionPrecheckParse.ok && isSubscriptionEnvelope(subscriptionPrecheckParse.data)) {
|
|
67919
|
+
const { chatType: subscriptionChatType, conversationId: subscriptionConversationId } = getConversationInfo(ctx.conversation);
|
|
67920
|
+
const gateDecision = decideSubscriptionGate({
|
|
67921
|
+
// getConversationInfo's declared StoredChatType also lists "system",
|
|
67922
|
+
// but that value is only ever produced for stored-message bookkeeping
|
|
67923
|
+
// elsewhere in this file — the conversation-type branch above never
|
|
67924
|
+
// returns it, so this narrowing is safe.
|
|
67925
|
+
chatType: subscriptionChatType === "system" ? "unknown" : subscriptionChatType,
|
|
67926
|
+
payload: subscriptionPrecheckParse.data,
|
|
67927
|
+
senderInboxId: ctx.message.senderInboxId ?? ""
|
|
67928
|
+
});
|
|
67929
|
+
return processSubscriptionInbound(ctx, deps, {
|
|
67930
|
+
decision: gateDecision,
|
|
67931
|
+
conversationId: subscriptionConversationId,
|
|
67932
|
+
messageId: messageId || `subscription-${(0, import_node_crypto13.randomUUID)()}`
|
|
67933
|
+
});
|
|
67934
|
+
}
|
|
66675
67935
|
if (messageId && !tryMarkProcessed(messageId)) {
|
|
66676
67936
|
logWithTimestamp(`[okx-agent-task:${deps.myXmtpAddress}] duplicate message ignored: ${messageId}`);
|
|
66677
67937
|
logger.info(LogEvent.INBOUND_IGNORED_DUPLICATE, timing.extras({
|
|
@@ -66694,19 +67954,6 @@ async function processFileMessage(ctx, deps, options = {}) {
|
|
|
66694
67954
|
chatType,
|
|
66695
67955
|
...extra
|
|
66696
67956
|
});
|
|
66697
|
-
if (chatType === "dm") {
|
|
66698
|
-
const dmTrustStartedAt = Date.now();
|
|
66699
|
-
const trusted = await isTrustedDmSender({
|
|
66700
|
-
myXmtpAddress: deps.myXmtpAddress,
|
|
66701
|
-
senderInboxId: ctx.message.senderInboxId ?? "",
|
|
66702
|
-
messageId,
|
|
66703
|
-
conversationId
|
|
66704
|
-
});
|
|
66705
|
-
timing.mark("dmTrustCheck", dmTrustStartedAt);
|
|
66706
|
-
if (!trusted) {
|
|
66707
|
-
return true;
|
|
66708
|
-
}
|
|
66709
|
-
}
|
|
66710
67957
|
const parseStartedAt = Date.now();
|
|
66711
67958
|
const receivedRawText = extractRawText(ctx.message.content);
|
|
66712
67959
|
const parseResult = parseJson2(receivedRawText);
|
|
@@ -66722,9 +67969,26 @@ async function processFileMessage(ctx, deps, options = {}) {
|
|
|
66722
67969
|
}
|
|
66723
67970
|
}
|
|
66724
67971
|
timing.mark("payloadParse", parseStartedAt);
|
|
67972
|
+
const parsedDmData = parseResult.ok ? parseResult.data : null;
|
|
67973
|
+
const parsedDmMessage = isPlainObject5(parsedDmData) && isPlainObject5(parsedDmData.message) ? parsedDmData.message : null;
|
|
67974
|
+
const dmCarriesSystemMarkers = parsedDmMessage?.isDirectToUser === true || parsedDmMessage?.source === "system" || parsedDmMessage?.isDirectCommunication === true;
|
|
67975
|
+
const isA2ADm = chatType === "dm" && parseResult.ok && isA2AEnvelope(parseResult.data) && !dmCarriesSystemMarkers;
|
|
67976
|
+
if (chatType === "dm" && !isA2ADm) {
|
|
67977
|
+
const dmTrustStartedAt = Date.now();
|
|
67978
|
+
const trusted = await isTrustedDmSender({
|
|
67979
|
+
myXmtpAddress: deps.myXmtpAddress,
|
|
67980
|
+
senderInboxId: ctx.message.senderInboxId ?? "",
|
|
67981
|
+
messageId,
|
|
67982
|
+
conversationId
|
|
67983
|
+
});
|
|
67984
|
+
timing.mark("dmTrustCheck", dmTrustStartedAt);
|
|
67985
|
+
if (!trusted) {
|
|
67986
|
+
return true;
|
|
67987
|
+
}
|
|
67988
|
+
}
|
|
66725
67989
|
const directToUser = chatType === "dm" && parseResult.ok ? extractDirectToUserNotification(parseResult.data) : { kind: "none" };
|
|
66726
67990
|
if (directToUser.kind === "invalid") {
|
|
66727
|
-
const droppedMessageId = messageId || `direct-to-user-${(0,
|
|
67991
|
+
const droppedMessageId = messageId || `direct-to-user-${(0, import_node_crypto13.randomUUID)()}`;
|
|
66728
67992
|
logger.error(
|
|
66729
67993
|
LogEvent.INBOUND_DROP_DM_INVALID_PAYLOAD,
|
|
66730
67994
|
new Error("Invalid direct-to-user system DM"),
|
|
@@ -66748,7 +68012,7 @@ async function processFileMessage(ctx, deps, options = {}) {
|
|
|
66748
68012
|
await dispatchDirectToUserNotification({
|
|
66749
68013
|
deps,
|
|
66750
68014
|
notification: directToUser.notification,
|
|
66751
|
-
messageId: messageId || `direct-to-user-${(0,
|
|
68015
|
+
messageId: messageId || `direct-to-user-${(0, import_node_crypto13.randomUUID)()}`,
|
|
66752
68016
|
timing,
|
|
66753
68017
|
source: options.source ?? "live"
|
|
66754
68018
|
});
|
|
@@ -66756,7 +68020,7 @@ async function processFileMessage(ctx, deps, options = {}) {
|
|
|
66756
68020
|
}
|
|
66757
68021
|
const systemNotification = chatType === "dm" && parseResult.ok ? extractSystemNotification(parseResult.data) : null;
|
|
66758
68022
|
if (systemNotification) {
|
|
66759
|
-
const systemMessageId = messageId || `system-${(0,
|
|
68023
|
+
const systemMessageId = messageId || `system-${(0, import_node_crypto13.randomUUID)()}`;
|
|
66760
68024
|
logWithTimestamp(
|
|
66761
68025
|
`[okx-agent-task:${deps.myXmtpAddress}] xmtp_system_message_received agentId=${systemNotification.agentId ?? ""} msg=${shortenLogValue(systemMessageId)} event=${systemNotification.event ?? ""} job=${shortenLogValue(systemNotification.jobId)} conv=${conversationId} source=${options.source ?? "live"} rawBytes=${Buffer.byteLength(rawText, "utf8")} rawPreview=${previewRawEnvelope(rawText)}`
|
|
66762
68026
|
);
|
|
@@ -66917,7 +68181,7 @@ async function processFileMessage(ctx, deps, options = {}) {
|
|
|
66917
68181
|
timing.mark("routeResolve", routeStartedAt);
|
|
66918
68182
|
if (route.route === "job" && parseResult.ok && isA2AEnvelope(parseResult.data) && !isValidExternalJobId(route.jobId)) {
|
|
66919
68183
|
const payloadObject = parseResult.data;
|
|
66920
|
-
const sender =
|
|
68184
|
+
const sender = isPlainObject5(payloadObject.sender) ? payloadObject.sender : null;
|
|
66921
68185
|
logWithTimestamp(
|
|
66922
68186
|
`[okx-agent-task:${deps.myXmtpAddress}] inbound A2A message has invalid jobId, dropping: jobLength=${route.jobId.length} group=${conversationId}`
|
|
66923
68187
|
);
|
|
@@ -66946,7 +68210,32 @@ async function processFileMessage(ctx, deps, options = {}) {
|
|
|
66946
68210
|
});
|
|
66947
68211
|
return true;
|
|
66948
68212
|
}
|
|
66949
|
-
if (route.route
|
|
68213
|
+
if (isA2ADm && route.route !== "job") {
|
|
68214
|
+
const payloadObject = parseResult.data;
|
|
68215
|
+
const sender = isPlainObject5(payloadObject.sender) ? payloadObject.sender : null;
|
|
68216
|
+
recordInvalidXmtpMessageBestEffort({
|
|
68217
|
+
messageId,
|
|
68218
|
+
groupId: conversationId,
|
|
68219
|
+
jobId: null,
|
|
68220
|
+
agentId: readString3(sender?.agentId),
|
|
68221
|
+
localAgentId: XmtpService.getInstance().getAgentByAddress(deps.myXmtpAddress)?.agentId ?? null,
|
|
68222
|
+
senderInboxId: ctx.message.senderInboxId ?? "",
|
|
68223
|
+
reason: "dm_a2a_missing_job_id",
|
|
68224
|
+
stage: "inbound/job_id_validation",
|
|
68225
|
+
logTag: `[okx-agent-task:${deps.myXmtpAddress}]`
|
|
68226
|
+
});
|
|
68227
|
+
logger.info(LogEvent.INBOUND_DROP_INVALID_JOBID, {
|
|
68228
|
+
...agentExtras({ walletAddress: deps.myXmtpAddress }),
|
|
68229
|
+
conversationId,
|
|
68230
|
+
messageId,
|
|
68231
|
+
chatType,
|
|
68232
|
+
peerInboxId: ctx.message.senderInboxId ?? "",
|
|
68233
|
+
...inboundStageExtras("inbound/job_id_validation", "dropped"),
|
|
68234
|
+
reason: "dm_a2a_missing_job_id"
|
|
68235
|
+
});
|
|
68236
|
+
return true;
|
|
68237
|
+
}
|
|
68238
|
+
if (route.route === "job" && chatType !== "group" && !isA2ADm) {
|
|
66950
68239
|
const providerBindStartedAt = Date.now();
|
|
66951
68240
|
const providerGate = await bindMessageJobProviderToCurrentDefault(deps, route.jobId, "inbound-xmtp");
|
|
66952
68241
|
timing.mark("providerBind", providerBindStartedAt);
|
|
@@ -66986,7 +68275,7 @@ async function processFileMessage(ctx, deps, options = {}) {
|
|
|
66986
68275
|
);
|
|
66987
68276
|
}
|
|
66988
68277
|
if (route.route === "job" && chatType === "group") {
|
|
66989
|
-
const payloadObject =
|
|
68278
|
+
const payloadObject = isPlainObject5(parseResult.ok ? parseResult.data : null) ? parseResult.data : null;
|
|
66990
68279
|
const service = XmtpService.getInstance();
|
|
66991
68280
|
const trustedSystemSender = service.isTrustedSystemAccountSender({
|
|
66992
68281
|
senderAddress,
|
|
@@ -67012,7 +68301,7 @@ async function processFileMessage(ctx, deps, options = {}) {
|
|
|
67012
68301
|
});
|
|
67013
68302
|
return true;
|
|
67014
68303
|
}
|
|
67015
|
-
const sender =
|
|
68304
|
+
const sender = isPlainObject5(payloadObject?.sender) ? payloadObject.sender : null;
|
|
67016
68305
|
const localAgent = service.getAgentByAddress(deps.myXmtpAddress);
|
|
67017
68306
|
const myAgentId = localAgent?.agentId ?? readString3(payloadObject?.receiverAgentId) ?? sessionAgentId ?? null;
|
|
67018
68307
|
const toAgentId = readString3(sender?.agentId);
|
|
@@ -67052,7 +68341,7 @@ async function processFileMessage(ctx, deps, options = {}) {
|
|
|
67052
68341
|
}));
|
|
67053
68342
|
return true;
|
|
67054
68343
|
}
|
|
67055
|
-
const routedMessageId = messageId || `group-${(0,
|
|
68344
|
+
const routedMessageId = messageId || `group-${(0, import_node_crypto13.randomUUID)()}`;
|
|
67056
68345
|
const sessionKey = ensureInboundGroupSession(deps, {
|
|
67057
68346
|
jobId: route.jobId,
|
|
67058
68347
|
myAgentId,
|
|
@@ -67117,8 +68406,102 @@ async function processFileMessage(ctx, deps, options = {}) {
|
|
|
67117
68406
|
);
|
|
67118
68407
|
return true;
|
|
67119
68408
|
}
|
|
68409
|
+
if (route.route === "job" && isA2ADm) {
|
|
68410
|
+
const payloadObject = parseResult.data;
|
|
68411
|
+
const accepted = await verifyInboundA2AGroupMessage({
|
|
68412
|
+
payload: parseResult.data,
|
|
68413
|
+
myXmtpAddress: deps.myXmtpAddress,
|
|
68414
|
+
senderAddress,
|
|
68415
|
+
senderInboxId: ctx.message.senderInboxId ?? "",
|
|
68416
|
+
jobId: route.jobId,
|
|
68417
|
+
groupId: conversationId,
|
|
68418
|
+
messageId,
|
|
68419
|
+
consentState: void 0,
|
|
68420
|
+
trustedSystemSender: false,
|
|
68421
|
+
isOfflineReplay: options.isOfflineReplay ?? false,
|
|
68422
|
+
timing
|
|
68423
|
+
});
|
|
68424
|
+
if (!accepted) {
|
|
68425
|
+
return true;
|
|
68426
|
+
}
|
|
68427
|
+
const providerBindStartedAt = Date.now();
|
|
68428
|
+
const providerGate = await bindMessageJobProviderToCurrentDefault(deps, route.jobId, "inbound-xmtp");
|
|
68429
|
+
timing.mark("providerBind", providerBindStartedAt);
|
|
68430
|
+
if (!providerGate.allowed) {
|
|
68431
|
+
logger.info(LogEvent.INBOUND_IGNORED_NON_BUSINESS, timing.extras({
|
|
68432
|
+
...buildInboundTerminalExtras({
|
|
68433
|
+
terminalState: "provider_gate_denied",
|
|
68434
|
+
myXmtpAddress: deps.myXmtpAddress,
|
|
68435
|
+
messageId,
|
|
68436
|
+
conversationId,
|
|
68437
|
+
chatType,
|
|
68438
|
+
jobId: route.jobId,
|
|
68439
|
+
route: route.route,
|
|
68440
|
+
reason: "job_provider_gate_denied"
|
|
68441
|
+
}),
|
|
68442
|
+
routeReason: route.routeReason,
|
|
68443
|
+
providerBinding: providerGate.provider ?? ""
|
|
68444
|
+
}));
|
|
68445
|
+
return true;
|
|
68446
|
+
}
|
|
68447
|
+
const myAgentId = XmtpService.getInstance().getAgentByAddress(deps.myXmtpAddress)?.agentId ?? readString3(payloadObject.receiverAgentId) ?? sessionAgentId ?? null;
|
|
68448
|
+
const sender = isPlainObject5(payloadObject.sender) ? payloadObject.sender : null;
|
|
68449
|
+
const toAgentId = readString3(sender?.agentId);
|
|
68450
|
+
const routedMessageId = messageId || `dm-${(0, import_node_crypto13.randomUUID)()}`;
|
|
68451
|
+
const sessionKey = ensureInboundGroupSession(deps, {
|
|
68452
|
+
jobId: route.jobId,
|
|
68453
|
+
myAgentId,
|
|
68454
|
+
toAgentId,
|
|
68455
|
+
groupId: null,
|
|
68456
|
+
toAgentXmtpAddress: senderAddress || readString3(payloadObject.fromXmtpAddress)
|
|
68457
|
+
});
|
|
68458
|
+
const dispatchStartedAt = Date.now();
|
|
68459
|
+
void Promise.resolve(deps.onSessionMessage?.({
|
|
68460
|
+
sessionKey,
|
|
68461
|
+
content: rawText,
|
|
68462
|
+
messageId: routedMessageId,
|
|
68463
|
+
jobId: route.jobId,
|
|
68464
|
+
agentId: myAgentId
|
|
68465
|
+
})).then(() => {
|
|
68466
|
+
timing.mark("sessionDispatch", dispatchStartedAt);
|
|
68467
|
+
logger.info(LogEvent.INBOUND_DELIVERED, commonDeliveryExtras({
|
|
68468
|
+
taskId: route.jobId,
|
|
68469
|
+
agentId: myAgentId ?? "",
|
|
68470
|
+
peerWalletAddress: senderAddress,
|
|
68471
|
+
peerInboxId: ctx.message.senderInboxId ?? "",
|
|
68472
|
+
peerAgentId: toAgentId ?? "",
|
|
68473
|
+
sessionKey,
|
|
68474
|
+
messageId: routedMessageId,
|
|
68475
|
+
route: "dm",
|
|
68476
|
+
...inboundStageExtras("inbound/dm_session_dispatch", "success"),
|
|
68477
|
+
dispatchTarget: deps.onSessionMessage ? "session" : "none"
|
|
68478
|
+
}));
|
|
68479
|
+
}).catch((err) => {
|
|
68480
|
+
logWithTimestamp(`[okx-agent-task:${deps.myXmtpAddress}] onSessionMessage failed:`, err);
|
|
68481
|
+
logger.error(LogEvent.INBOUND_DISPATCH_FAILED, toLoggableError(err), timing.extras({
|
|
68482
|
+
...buildInboundTerminalExtras({
|
|
68483
|
+
terminalState: "dispatch_failed",
|
|
68484
|
+
myXmtpAddress: deps.myXmtpAddress,
|
|
68485
|
+
messageId: routedMessageId,
|
|
68486
|
+
conversationId,
|
|
68487
|
+
chatType,
|
|
68488
|
+
jobId: route.jobId,
|
|
68489
|
+
sessionKey,
|
|
68490
|
+
route: "dm",
|
|
68491
|
+
reason: "session_dispatch_failed"
|
|
68492
|
+
}),
|
|
68493
|
+
checkpoint: "inbound/dm_session_dispatch_failed",
|
|
68494
|
+
agentId: myAgentId ?? "",
|
|
68495
|
+
peerAgentId: toAgentId ?? ""
|
|
68496
|
+
}));
|
|
68497
|
+
});
|
|
68498
|
+
logWithTimestamp(
|
|
68499
|
+
`[okx-agent-task:${deps.myXmtpAddress}] session dispatch queued route=dm session=${sessionKey} message=${shortenLogValue(routedMessageId)} ${summarizePayloadForLog(parseResult.data)}`
|
|
68500
|
+
);
|
|
68501
|
+
return true;
|
|
68502
|
+
}
|
|
67120
68503
|
const stored = {
|
|
67121
|
-
id: messageId || `local-${(0,
|
|
68504
|
+
id: messageId || `local-${(0, import_node_crypto13.randomUUID)()}`,
|
|
67122
68505
|
direction: "inbound",
|
|
67123
68506
|
route: route.route,
|
|
67124
68507
|
routeReason: route.routeReason,
|
|
@@ -67136,8 +68519,8 @@ async function processFileMessage(ctx, deps, options = {}) {
|
|
|
67136
68519
|
await deps.store.append(route.jobId, stored, sessionAgentId);
|
|
67137
68520
|
timing.mark("storeAppend", storeAppendStartedAt);
|
|
67138
68521
|
if ((route.route === "job" || parseResult.ok && !isA2AEnvelope(stored.payload)) && !options.skipNotify) {
|
|
67139
|
-
const payloadObject =
|
|
67140
|
-
const sender =
|
|
68522
|
+
const payloadObject = isPlainObject5(stored.payload) ? stored.payload : null;
|
|
68523
|
+
const sender = isPlainObject5(payloadObject?.sender) ? payloadObject.sender : null;
|
|
67141
68524
|
const localAgent = XmtpService.getInstance().getAgentByAddress(deps.myXmtpAddress);
|
|
67142
68525
|
const sessionKey = route.route === "job" ? buildSessionKey({
|
|
67143
68526
|
jobId: route.jobId,
|
|
@@ -67155,8 +68538,8 @@ async function processFileMessage(ctx, deps, options = {}) {
|
|
|
67155
68538
|
});
|
|
67156
68539
|
}
|
|
67157
68540
|
if (route.route === "job" && chatType === "group" && conversationId && senderAddress) {
|
|
67158
|
-
const payloadObject =
|
|
67159
|
-
const sender =
|
|
68541
|
+
const payloadObject = isPlainObject5(stored.payload) ? stored.payload : null;
|
|
68542
|
+
const sender = isPlainObject5(payloadObject?.sender) ? payloadObject.sender : null;
|
|
67160
68543
|
await deps.store.updateXmtpSession(route.jobId, {
|
|
67161
68544
|
xmtpGroupId: conversationId,
|
|
67162
68545
|
myXmtpAddress: deps.myXmtpAddress,
|
|
@@ -67299,7 +68682,7 @@ function processOfflineFromCoreDeps(store, ctx, deps, options) {
|
|
|
67299
68682
|
function buildSystemStoredMessage(params) {
|
|
67300
68683
|
const now = Date.now();
|
|
67301
68684
|
return {
|
|
67302
|
-
id: params.id ?? `system-${now}-${(0,
|
|
68685
|
+
id: params.id ?? `system-${now}-${(0, import_node_crypto13.randomUUID)()}`,
|
|
67303
68686
|
direction: "system",
|
|
67304
68687
|
route: "backup",
|
|
67305
68688
|
routeReason: params.reason,
|
|
@@ -67315,7 +68698,7 @@ function buildSystemStoredMessage(params) {
|
|
|
67315
68698
|
};
|
|
67316
68699
|
}
|
|
67317
68700
|
function isA2AEnvelope(payload) {
|
|
67318
|
-
return
|
|
68701
|
+
return isPlainObject5(payload) && payload.msgType === A2A_MESSAGE_TYPE;
|
|
67319
68702
|
}
|
|
67320
68703
|
|
|
67321
68704
|
// src/listener.ts
|
|
@@ -67443,7 +68826,7 @@ async function enqueueAiJobMessageDispatch(params) {
|
|
|
67443
68826
|
await commands.submit(command);
|
|
67444
68827
|
return command;
|
|
67445
68828
|
}
|
|
67446
|
-
async function
|
|
68829
|
+
async function enqueueAiSessionMessageDispatchIdempotent(params) {
|
|
67447
68830
|
const commands = params.commands ?? new CommandStore(params.homeDir);
|
|
67448
68831
|
const messageId = params.event.messageId ?? `session-${Date.now()}`;
|
|
67449
68832
|
const command = commands.createAiSessionMessageDispatchCommand({
|
|
@@ -67453,15 +68836,25 @@ async function enqueueAiSessionMessageDispatch(params) {
|
|
|
67453
68836
|
jobId: params.event.jobId,
|
|
67454
68837
|
agentId: params.event.agentId
|
|
67455
68838
|
});
|
|
68839
|
+
const idempotencyKey = params.event.idempotencyKey?.trim();
|
|
68840
|
+
if (idempotencyKey) {
|
|
68841
|
+
const dbKey = `${command.sessionKey}
|
|
68842
|
+
${command.messageId}`;
|
|
68843
|
+
const result = await commands.submitIdempotent(command, dbKey);
|
|
68844
|
+
return {
|
|
68845
|
+
command: result.created ? command : { ...command, id: result.commandId },
|
|
68846
|
+
created: result.created
|
|
68847
|
+
};
|
|
68848
|
+
}
|
|
67456
68849
|
await commands.submit(command);
|
|
67457
|
-
return command;
|
|
68850
|
+
return { command, created: true };
|
|
67458
68851
|
}
|
|
67459
68852
|
|
|
67460
68853
|
// src/listener.ts
|
|
67461
68854
|
init_paths();
|
|
67462
68855
|
|
|
67463
68856
|
// src/user-attention-watchers.ts
|
|
67464
|
-
var
|
|
68857
|
+
var import_node_crypto14 = require("node:crypto");
|
|
67465
68858
|
init_sentry_logger();
|
|
67466
68859
|
var USER_ATTENTION_WATCH_REPLACED_MESSAGE = "Another okx-a2a user watch with the same job scope was started, so this watcher has been closed. Do not run this watch command again automatically, because starting another watcher may interrupt a different session that is already monitoring task progress.";
|
|
67467
68860
|
var USER_ATTENTION_WATCHER_SCAN_MS = 500;
|
|
@@ -67504,7 +68897,7 @@ function isOriginalParentProcessAlive(options) {
|
|
|
67504
68897
|
}
|
|
67505
68898
|
function registerUserAttentionWatcher(options) {
|
|
67506
68899
|
return options.store.registerUserAttentionWatcher({
|
|
67507
|
-
id: options.id ?? (0,
|
|
68900
|
+
id: options.id ?? (0, import_node_crypto14.randomUUID)(),
|
|
67508
68901
|
provider: options.provider,
|
|
67509
68902
|
jobId: options.jobId,
|
|
67510
68903
|
nowMs: options.nowMs ?? Date.now(),
|
|
@@ -67796,6 +69189,35 @@ var ListenerMaintenanceGate = class {
|
|
|
67796
69189
|
}
|
|
67797
69190
|
};
|
|
67798
69191
|
var UPGRADE_RECOMMENDATION_IDEMPOTENCY_KEY = "system:onchainos-offline-replay-upgrade";
|
|
69192
|
+
var LIST_JOBS_UPGRADE_RECOMMENDATION_IDEMPOTENCY_KEY = "system:onchainos-list-jobs-by-verified-sender-upgrade";
|
|
69193
|
+
function buildUpgradeRecommendationNotice(input) {
|
|
69194
|
+
const capability = input.capability?.trim() ?? "";
|
|
69195
|
+
if (capability === MESSAGE_ELIGIBLE_OFFLINE_REPLAY_HELP_TOKEN) {
|
|
69196
|
+
return {
|
|
69197
|
+
title: "OnchainOS upgrade recommended",
|
|
69198
|
+
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",
|
|
69199
|
+
idempotencyKey: UPGRADE_RECOMMENDATION_IDEMPOTENCY_KEY
|
|
69200
|
+
};
|
|
69201
|
+
}
|
|
69202
|
+
if (capability === LIST_JOBS_BY_VERIFIED_SENDER_HELP_TOKEN) {
|
|
69203
|
+
return {
|
|
69204
|
+
title: "OnchainOS upgrade required for Subscription Shared Group",
|
|
69205
|
+
content: "The installed OnchainOS version does not support the verified-sender task query required by Subscription Shared Group. Until OnchainOS is upgraded, Subscription Shared Group messages fail closed and are NOT routed to an AI Session. Upgrade OnchainOS to enable this capability.\n\nSuggested command: onchainos upgrade",
|
|
69206
|
+
idempotencyKey: LIST_JOBS_UPGRADE_RECOMMENDATION_IDEMPOTENCY_KEY
|
|
69207
|
+
};
|
|
69208
|
+
}
|
|
69209
|
+
const capabilitySlug = capability ? capability.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") : "";
|
|
69210
|
+
const idempotencyKey = capabilitySlug ? `system:onchainos-${capabilitySlug}-upgrade` : "system:onchainos-capability-upgrade";
|
|
69211
|
+
const capabilityLabel = capability || "a required capability";
|
|
69212
|
+
const reasonSuffix = input.reason?.trim() ? ` ${input.reason.trim()}` : "";
|
|
69213
|
+
return {
|
|
69214
|
+
title: "OnchainOS upgrade recommended",
|
|
69215
|
+
content: `The installed OnchainOS version does not support ${capabilityLabel}.${reasonSuffix} Upgrade OnchainOS to enable this capability.
|
|
69216
|
+
|
|
69217
|
+
Suggested command: onchainos upgrade`,
|
|
69218
|
+
idempotencyKey
|
|
69219
|
+
};
|
|
69220
|
+
}
|
|
67799
69221
|
function resolveOfflineReplayIntervalSec(systemConfig) {
|
|
67800
69222
|
const interval = systemConfig.offlineReplayInterval;
|
|
67801
69223
|
if (typeof interval !== "number" || !Number.isFinite(interval) || interval <= 0) {
|
|
@@ -68024,8 +69446,12 @@ async function runListenerWithLock(options, paths) {
|
|
|
68024
69446
|
onJobMessageStored: async (event) => {
|
|
68025
69447
|
await enqueueAiJobMessageDispatch({ commands, event });
|
|
68026
69448
|
},
|
|
69449
|
+
// Returns { created } so the V2 subscription fan-out can distinguish a
|
|
69450
|
+
// durable DB duplicate (idempotent success) from a fresh enqueue. V1
|
|
69451
|
+
// group/system callers ignore the return; their events carry no
|
|
69452
|
+
// idempotencyKey, so the plain submit path (unchanged) is used.
|
|
68027
69453
|
onSessionMessage: async (event) => {
|
|
68028
|
-
|
|
69454
|
+
return enqueueAiSessionMessageDispatchIdempotent({ commands, event });
|
|
68029
69455
|
}
|
|
68030
69456
|
}),
|
|
68031
69457
|
processOfflineMessage: (ctx, deps, replayOptions) => processOfflineFromCoreDeps(store, ctx, deps, {
|
|
@@ -68035,7 +69461,7 @@ async function runListenerWithLock(options, paths) {
|
|
|
68035
69461
|
await enqueueAiJobMessageDispatch({ commands, event });
|
|
68036
69462
|
},
|
|
68037
69463
|
onSessionMessage: async (event) => {
|
|
68038
|
-
|
|
69464
|
+
return enqueueAiSessionMessageDispatchIdempotent({ commands, event });
|
|
68039
69465
|
}
|
|
68040
69466
|
}),
|
|
68041
69467
|
notifySessionExpired: (command) => {
|
|
@@ -68053,12 +69479,12 @@ async function runListenerWithLock(options, paths) {
|
|
|
68053
69479
|
});
|
|
68054
69480
|
},
|
|
68055
69481
|
notifyUpgradeRecommendation: (input) => {
|
|
68056
|
-
const
|
|
69482
|
+
const notice = buildUpgradeRecommendationNotice(input);
|
|
68057
69483
|
void notifySystemMessageToUser({
|
|
68058
|
-
title:
|
|
68059
|
-
content,
|
|
69484
|
+
title: notice.title,
|
|
69485
|
+
content: notice.content,
|
|
68060
69486
|
store: sessionStore,
|
|
68061
|
-
idempotencyKey:
|
|
69487
|
+
idempotencyKey: notice.idempotencyKey
|
|
68062
69488
|
}).catch((err) => {
|
|
68063
69489
|
logWithTimestamp(
|
|
68064
69490
|
`[okx-agent-task] upgrade recommendation notify failed component=${input.component} capability=${input.capability}:`,
|
|
@@ -68067,12 +69493,12 @@ async function runListenerWithLock(options, paths) {
|
|
|
68067
69493
|
});
|
|
68068
69494
|
}
|
|
68069
69495
|
});
|
|
68070
|
-
service.setPluginVersion("0.2.
|
|
69496
|
+
service.setPluginVersion("0.2.18-beta-4dd056b897-261015113839");
|
|
68071
69497
|
await service.init();
|
|
68072
69498
|
const pluginVersionStatus = service.pluginVersionStatus;
|
|
68073
69499
|
if (pluginVersionStatus.unavailable) {
|
|
68074
69500
|
throw new Error(
|
|
68075
|
-
`@okxweb3/a2a-node v${"0.2.
|
|
69501
|
+
`@okxweb3/a2a-node v${"0.2.18-beta-4dd056b897-261015113839"} is below the required minimum v${pluginVersionStatus.minVersion}`
|
|
68076
69502
|
);
|
|
68077
69503
|
}
|
|
68078
69504
|
const systemConfig = service.getSystemConfig();
|
|
@@ -68100,7 +69526,7 @@ async function runListenerWithLock(options, paths) {
|
|
|
68100
69526
|
onchainosAgentId: "*",
|
|
68101
69527
|
reason: "system-config missing sentryDsn",
|
|
68102
69528
|
pluginId: "@okxweb3/a2a-node",
|
|
68103
|
-
pluginVersion: "0.2.
|
|
69529
|
+
pluginVersion: "0.2.18-beta-4dd056b897-261015113839"
|
|
68104
69530
|
});
|
|
68105
69531
|
}
|
|
68106
69532
|
logWithTimestamp(
|
|
@@ -69562,7 +70988,7 @@ var import_node_path34 = require("node:path");
|
|
|
69562
70988
|
var import_jszip = __toESM(require_lib3());
|
|
69563
70989
|
|
|
69564
70990
|
// src/logs-export-archive.ts
|
|
69565
|
-
var
|
|
70991
|
+
var import_node_crypto15 = require("node:crypto");
|
|
69566
70992
|
var import_node_fs24 = require("node:fs");
|
|
69567
70993
|
var import_promises13 = require("node:fs/promises");
|
|
69568
70994
|
var import_node_path31 = require("node:path");
|
|
@@ -70198,7 +71624,7 @@ async function writeArchiveAtomically(outputPath, archive, overwrite) {
|
|
|
70198
71624
|
await (0, import_promises13.mkdir)((0, import_node_path31.dirname)(outputPath), { recursive: true });
|
|
70199
71625
|
const temporaryPath = (0, import_node_path31.join)(
|
|
70200
71626
|
(0, import_node_path31.dirname)(outputPath),
|
|
70201
|
-
`.${(0, import_node_path31.basename)(outputPath)}.${(0,
|
|
71627
|
+
`.${(0, import_node_path31.basename)(outputPath)}.${(0, import_node_crypto15.randomUUID)()}.tmp`
|
|
70202
71628
|
);
|
|
70203
71629
|
try {
|
|
70204
71630
|
await (0, import_promises13.writeFile)(temporaryPath, archive, { flag: "wx", mode: 384 });
|
|
@@ -70217,7 +71643,7 @@ async function writeArchiveAtomically(outputPath, archive, overwrite) {
|
|
|
70217
71643
|
}
|
|
70218
71644
|
}
|
|
70219
71645
|
function hashDiagnosticFileContent(content) {
|
|
70220
|
-
return (0,
|
|
71646
|
+
return (0, import_node_crypto15.createHash)("sha256").update(content).digest("hex");
|
|
70221
71647
|
}
|
|
70222
71648
|
function isUnavailableError(err) {
|
|
70223
71649
|
return !!err && typeof err === "object" && "diagnosticUnavailable" in err;
|
|
@@ -70477,7 +71903,7 @@ function isProvider2(value) {
|
|
|
70477
71903
|
}
|
|
70478
71904
|
|
|
70479
71905
|
// src/logs-export-utils.ts
|
|
70480
|
-
var
|
|
71906
|
+
var import_node_crypto16 = require("node:crypto");
|
|
70481
71907
|
var import_node_fs26 = require("node:fs");
|
|
70482
71908
|
var import_promises14 = require("node:fs/promises");
|
|
70483
71909
|
var import_node_path33 = require("node:path");
|
|
@@ -70620,7 +72046,7 @@ async function assertRegularFile2(path2) {
|
|
|
70620
72046
|
}
|
|
70621
72047
|
async function inspectRegularFile(path2) {
|
|
70622
72048
|
const file = await assertRegularFile2(path2);
|
|
70623
|
-
const hash2 = (0,
|
|
72049
|
+
const hash2 = (0, import_node_crypto16.createHash)("sha256");
|
|
70624
72050
|
for await (const chunk of (0, import_node_fs26.createReadStream)(path2)) {
|
|
70625
72051
|
hash2.update(chunk);
|
|
70626
72052
|
}
|
|
@@ -70873,7 +72299,7 @@ async function exportDiagnosticLogs(options) {
|
|
|
70873
72299
|
node: process.version,
|
|
70874
72300
|
platform: process.platform,
|
|
70875
72301
|
arch: process.arch,
|
|
70876
|
-
packageVersion: true ? "0.2.
|
|
72302
|
+
packageVersion: true ? "0.2.18-beta-4dd056b897-261015113839" : "unknown",
|
|
70877
72303
|
sensitiveContentIncluded: options.includeSensitiveContent,
|
|
70878
72304
|
listenerAndLlmContentIncluded: true,
|
|
70879
72305
|
credentialsAlwaysRedacted: true,
|
|
@@ -72785,7 +74211,7 @@ async function runDoctor(options = {}) {
|
|
|
72785
74211
|
platform: options.platform ?? process.platform,
|
|
72786
74212
|
env: options.env ?? process.env,
|
|
72787
74213
|
target: options.target ?? resolveDoctorTarget(options.env ?? process.env),
|
|
72788
|
-
cliVersion: options.cliVersion ?? (true ? "0.2.
|
|
74214
|
+
cliVersion: options.cliVersion ?? (true ? "0.2.18-beta-4dd056b897-261015113839" : "0.0.0"),
|
|
72789
74215
|
fixMode: options.fix === true,
|
|
72790
74216
|
nonInteractive: options.nonInteractive === true,
|
|
72791
74217
|
packageChanged: false,
|
|
@@ -73032,6 +74458,7 @@ init_autostart_windows();
|
|
|
73032
74458
|
InboundReplayGate,
|
|
73033
74459
|
InvalidXmtpMessageStore,
|
|
73034
74460
|
JOB_PROVIDER_BINDING_SOURCES,
|
|
74461
|
+
LIST_JOBS_BY_VERIFIED_SENDER_HELP_TOKEN,
|
|
73035
74462
|
ListenerDeferredTaskScheduler,
|
|
73036
74463
|
ListenerMaintenanceGate,
|
|
73037
74464
|
LogEvent,
|
|
@@ -73041,6 +74468,9 @@ init_autostart_windows();
|
|
|
73041
74468
|
NATIVE_LAUNCHER_EXE_NAME,
|
|
73042
74469
|
OPENCLAW_GATEWAY_ROUTE_GROUP_ID,
|
|
73043
74470
|
ProviderNotReadyError,
|
|
74471
|
+
RUN_LOG_FILENAME_MAX_BYTES,
|
|
74472
|
+
SUBSCRIPTION_FANOUT_MAX,
|
|
74473
|
+
SUBSCRIPTION_MESSAGE_TYPE,
|
|
73044
74474
|
SYSTEM_NOTIFICATION_SESSION_KEY,
|
|
73045
74475
|
SessionBusyTracker,
|
|
73046
74476
|
SessionStore,
|
|
@@ -73086,7 +74516,9 @@ init_autostart_windows();
|
|
|
73086
74516
|
buildInboundTerminalExtras,
|
|
73087
74517
|
buildLaunchdPlist,
|
|
73088
74518
|
buildLauncherEntryJs,
|
|
74519
|
+
buildListJobsByVerifiedSenderArgs,
|
|
73089
74520
|
buildMessageEligibleArgs,
|
|
74521
|
+
buildRunLogFileName,
|
|
73090
74522
|
buildSchtasksCreateArgs,
|
|
73091
74523
|
buildSchtasksDeleteArgs,
|
|
73092
74524
|
buildSchtasksEndArgs,
|
|
@@ -73095,9 +74527,14 @@ init_autostart_windows();
|
|
|
73095
74527
|
buildSeaConfig,
|
|
73096
74528
|
buildServicePath,
|
|
73097
74529
|
buildSessionKey,
|
|
74530
|
+
buildSubscriptionEnvelope,
|
|
74531
|
+
buildSubscriptionInboundExtras,
|
|
74532
|
+
buildSubscriptionJobExtras,
|
|
74533
|
+
buildSubscriptionSendExtras,
|
|
73098
74534
|
buildSystemMessageNotice,
|
|
73099
74535
|
buildSystemStoredMessage,
|
|
73100
74536
|
buildSystemdUserService,
|
|
74537
|
+
buildUpgradeRecommendationNotice,
|
|
73101
74538
|
buildWin32OnchainosCandidates,
|
|
73102
74539
|
buildWindowsParentProcessProbe,
|
|
73103
74540
|
buildXmtpMessageSentExtra,
|
|
@@ -73112,6 +74549,7 @@ init_autostart_windows();
|
|
|
73112
74549
|
checkCodexReadiness,
|
|
73113
74550
|
claimActiveDaemon,
|
|
73114
74551
|
classifyJobBindingSource,
|
|
74552
|
+
classifyListJobsError,
|
|
73115
74553
|
clearCodexReadinessCache,
|
|
73116
74554
|
codexCommandResolvesWithoutOverride,
|
|
73117
74555
|
codexReadinessCacheKey,
|
|
@@ -73123,10 +74561,12 @@ init_autostart_windows();
|
|
|
73123
74561
|
createOutboundBehavior,
|
|
73124
74562
|
createUserAttentionWatchParentMonitor,
|
|
73125
74563
|
currentOpenClawGatewaySessionKey,
|
|
74564
|
+
decideSubscriptionGate,
|
|
73126
74565
|
detectAiProviders,
|
|
73127
74566
|
detectAiRuntimeSurface,
|
|
73128
74567
|
detectCurrentAiProvider,
|
|
73129
74568
|
detectGatewayInvocation,
|
|
74569
|
+
detectListJobsByVerifiedSenderSupport,
|
|
73130
74570
|
detectMessageEligibleOfflineReplaySupport,
|
|
73131
74571
|
detectRuntime,
|
|
73132
74572
|
ensureDaemonReady,
|
|
@@ -73140,6 +74580,7 @@ init_autostart_windows();
|
|
|
73140
74580
|
extractDirectToUserNotification,
|
|
73141
74581
|
extractRateLimitEndpoint,
|
|
73142
74582
|
extractXmtpSentAtMs,
|
|
74583
|
+
fanOutSubscriptionJobs,
|
|
73143
74584
|
findWindowsNativeOkxA2aExe,
|
|
73144
74585
|
followFile,
|
|
73145
74586
|
formatDoctorReportForHumans,
|
|
@@ -73152,6 +74593,7 @@ init_autostart_windows();
|
|
|
73152
74593
|
getXmtpCreationCooldown,
|
|
73153
74594
|
handleCapabilitiesCommand,
|
|
73154
74595
|
handleDoctorCommand,
|
|
74596
|
+
handleSubscriptionPushCommand,
|
|
73155
74597
|
handleXmtpDebugCommand,
|
|
73156
74598
|
handleXmtpSendCommand,
|
|
73157
74599
|
handleXmtpTestCommand,
|
|
@@ -73166,6 +74608,7 @@ init_autostart_windows();
|
|
|
73166
74608
|
invalidateResolvedOnchainosBinForTests,
|
|
73167
74609
|
isAutostartManagerUnavailableError,
|
|
73168
74610
|
isDefaultTaskHome,
|
|
74611
|
+
isFingerprintKey,
|
|
73169
74612
|
isGatewayAvailableForHeartbeat,
|
|
73170
74613
|
isHermesGatewayPluginEnabled,
|
|
73171
74614
|
isInfoEventAllowlisted,
|
|
@@ -73176,6 +74619,7 @@ init_autostart_windows();
|
|
|
73176
74619
|
isPrereleaseVersion,
|
|
73177
74620
|
isRetryableOpenClawGatewayError,
|
|
73178
74621
|
isSqliteBusyError,
|
|
74622
|
+
isSubscriptionEnvelope,
|
|
73179
74623
|
isSystemdManagerUnavailableMessage,
|
|
73180
74624
|
isTagKey,
|
|
73181
74625
|
isValidExternalJobId,
|
|
@@ -73184,8 +74628,12 @@ init_autostart_windows();
|
|
|
73184
74628
|
killProcessTree,
|
|
73185
74629
|
launchdPlistHasCurrentRestartPolicy,
|
|
73186
74630
|
listAllAgentsWithMetadata,
|
|
74631
|
+
listJobsByVerifiedSender,
|
|
74632
|
+
listJobsByVerifiedSenderHelpAdvertisesCommand,
|
|
74633
|
+
listJobsByVerifiedSenderWithCapability,
|
|
73187
74634
|
logWinCompat,
|
|
73188
74635
|
logXmtpMessageSent,
|
|
74636
|
+
logger,
|
|
73189
74637
|
maybeRecommendOnchainosUpgrade,
|
|
73190
74638
|
mergeA2AEnvelopeTips,
|
|
73191
74639
|
messageEligibleHelpAdvertisesOfflineReplay,
|
|
@@ -73193,6 +74641,8 @@ init_autostart_windows();
|
|
|
73193
74641
|
normalizeAiProvider,
|
|
73194
74642
|
normalizeAiRuntimeProvider,
|
|
73195
74643
|
normalizeHermesOkxA2aPluginConfig,
|
|
74644
|
+
normalizeListJobsResponse,
|
|
74645
|
+
normalizeSubscriptionJobs,
|
|
73196
74646
|
notifyAgentMessageToUserAttention,
|
|
73197
74647
|
notifyDirectToUserAttention,
|
|
73198
74648
|
notifySystemMessageToUser,
|
|
@@ -73203,6 +74653,7 @@ init_autostart_windows();
|
|
|
73203
74653
|
parsePluginYamlVersion,
|
|
73204
74654
|
parseWalletLoginStatus,
|
|
73205
74655
|
parseWindowsParentProcessJson,
|
|
74656
|
+
partitionSubscriptionJobsByOwner,
|
|
73206
74657
|
performRuntimeSwitch,
|
|
73207
74658
|
persistAiRuntimeSurfaceBestEffort,
|
|
73208
74659
|
persistCurrentRuntimeSelectionForNewJob,
|
|
@@ -73212,12 +74663,14 @@ init_autostart_windows();
|
|
|
73212
74663
|
printXmtpTestUsage,
|
|
73213
74664
|
probeCodexAuthStatus,
|
|
73214
74665
|
processFileMessage,
|
|
74666
|
+
processSubscriptionInbound,
|
|
73215
74667
|
queryWalletLoginStatus,
|
|
73216
74668
|
readAiProviderTimeoutMs,
|
|
73217
74669
|
readAiRuntimeSurfaceBestEffort,
|
|
73218
74670
|
readCachedCodexReadiness,
|
|
73219
74671
|
readLastLines,
|
|
73220
74672
|
readParentProcessCommandForPlatform,
|
|
74673
|
+
readSubscriptionEnvelope,
|
|
73221
74674
|
readUserAttentionWatcherEvent,
|
|
73222
74675
|
refreshAgentsAndWait,
|
|
73223
74676
|
refreshOnchainosVersionMetadata,
|
|
@@ -73228,8 +74681,10 @@ init_autostart_windows();
|
|
|
73228
74681
|
replayScanBackoffWithJitterMs,
|
|
73229
74682
|
reportDoctorRunToSentry,
|
|
73230
74683
|
reportUserNotificationFailure,
|
|
74684
|
+
resetListJobsByVerifiedSenderCapabilityForTests,
|
|
73231
74685
|
resetMessageEligibleOfflineReplayCapabilityForTests,
|
|
73232
74686
|
resetResolvedOnchainosBinForTests,
|
|
74687
|
+
resetSubscriptionTargetsForTests,
|
|
73233
74688
|
resetXmtpCreationCooldownForTests,
|
|
73234
74689
|
resolveAiPermissionPreset,
|
|
73235
74690
|
resolveAiProviderCommand,
|
|
@@ -73283,6 +74738,8 @@ init_autostart_windows();
|
|
|
73283
74738
|
stopOpenClawGateway,
|
|
73284
74739
|
stopSystemdAutostart,
|
|
73285
74740
|
subscribeUserAttentionEvents,
|
|
74741
|
+
subscriptionIdempotencyKey,
|
|
74742
|
+
summarizeSubscriptionPush,
|
|
73286
74743
|
summarizeXmtpTestEvents,
|
|
73287
74744
|
switchProvider,
|
|
73288
74745
|
switchProviderWithReadinessGate,
|
|
@@ -73291,6 +74748,7 @@ init_autostart_windows();
|
|
|
73291
74748
|
tailFile,
|
|
73292
74749
|
toOpenClawGatewaySessionKey,
|
|
73293
74750
|
toWindowsInvocation,
|
|
74751
|
+
tryMarkSubscriptionTarget,
|
|
73294
74752
|
writeAiPermissionPresetToConfig
|
|
73295
74753
|
});
|
|
73296
74754
|
/*! Bundled license information:
|