@okxweb3/a2a-node 0.2.8 → 0.2.9-beta-912b775358-260824171011
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 +760 -112
- package/dist/index.js +725 -91
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -3992,6 +3992,34 @@ var init_command_store = __esm({
|
|
|
3992
3992
|
}
|
|
3993
3993
|
return null;
|
|
3994
3994
|
}
|
|
3995
|
+
/**
|
|
3996
|
+
* Read-only lookup of a command's current lifecycle state by id. Returns null
|
|
3997
|
+
* when no row exists. Used by the WakeupNotify recovery reconcile to decide
|
|
3998
|
+
* whether an in-flight wakeup's command completed, failed, or was orphaned by a
|
|
3999
|
+
* crash — it does not mutate the queue or alter recovery behavior.
|
|
4000
|
+
*/
|
|
4001
|
+
getCommandState(commandId) {
|
|
4002
|
+
const row = this.db.prepare(`
|
|
4003
|
+
SELECT status, result_json, processing_started_at_ms FROM command_queue
|
|
4004
|
+
WHERE id = ?
|
|
4005
|
+
`).get(commandId);
|
|
4006
|
+
if (!row?.status) {
|
|
4007
|
+
return null;
|
|
4008
|
+
}
|
|
4009
|
+
let ok = null;
|
|
4010
|
+
if (row.result_json) {
|
|
4011
|
+
try {
|
|
4012
|
+
ok = Boolean(JSON.parse(row.result_json).ok);
|
|
4013
|
+
} catch {
|
|
4014
|
+
ok = null;
|
|
4015
|
+
}
|
|
4016
|
+
}
|
|
4017
|
+
return {
|
|
4018
|
+
status: row.status,
|
|
4019
|
+
ok,
|
|
4020
|
+
processingStartedAtMs: row.processing_started_at_ms ?? null
|
|
4021
|
+
};
|
|
4022
|
+
}
|
|
3995
4023
|
close() {
|
|
3996
4024
|
this.db.close();
|
|
3997
4025
|
}
|
|
@@ -4677,7 +4705,7 @@ var require_is = __commonJS({
|
|
|
4677
4705
|
function isPrimitive(wat) {
|
|
4678
4706
|
return wat === null || typeof wat !== "object" && typeof wat !== "function";
|
|
4679
4707
|
}
|
|
4680
|
-
function
|
|
4708
|
+
function isPlainObject6(wat) {
|
|
4681
4709
|
return isBuiltin(wat, "Object");
|
|
4682
4710
|
}
|
|
4683
4711
|
function isEvent(wat) {
|
|
@@ -4693,7 +4721,7 @@ var require_is = __commonJS({
|
|
|
4693
4721
|
return Boolean(wat && wat.then && typeof wat.then === "function");
|
|
4694
4722
|
}
|
|
4695
4723
|
function isSyntheticEvent(wat) {
|
|
4696
|
-
return
|
|
4724
|
+
return isPlainObject6(wat) && "nativeEvent" in wat && "preventDefault" in wat && "stopPropagation" in wat;
|
|
4697
4725
|
}
|
|
4698
4726
|
function isNaN2(wat) {
|
|
4699
4727
|
return typeof wat === "number" && wat !== wat;
|
|
@@ -4716,7 +4744,7 @@ var require_is = __commonJS({
|
|
|
4716
4744
|
exports2.isEvent = isEvent;
|
|
4717
4745
|
exports2.isInstanceOf = isInstanceOf;
|
|
4718
4746
|
exports2.isNaN = isNaN2;
|
|
4719
|
-
exports2.isPlainObject =
|
|
4747
|
+
exports2.isPlainObject = isPlainObject6;
|
|
4720
4748
|
exports2.isPrimitive = isPrimitive;
|
|
4721
4749
|
exports2.isRegExp = isRegExp;
|
|
4722
4750
|
exports2.isString = isString;
|
|
@@ -19969,6 +19997,17 @@ var init_events = __esm({
|
|
|
19969
19997
|
SYSTEM_NOTIFICATION_ROUTED: "System notification routed",
|
|
19970
19998
|
HERMES_SESSION_ROUTE_BINDING: "Hermes session route binding",
|
|
19971
19999
|
DOCTOR_REPORT: "Doctor report",
|
|
20000
|
+
// Paginated WakeupNotify recovery (BL-011) + bounded AI concurrency telemetry.
|
|
20001
|
+
// All info-level events below must ALSO be listed in SENTRY_INFO_ALLOWLIST
|
|
20002
|
+
// (index.ts) or info() drops them silently.
|
|
20003
|
+
WAKEUP_PULL_STARTED: "WakeupNotify pull started",
|
|
20004
|
+
WAKEUP_PULL_PAGE_FETCHED: "WakeupNotify pull page fetched",
|
|
20005
|
+
WAKEUP_PULL_PAGE_RETRY: "WakeupNotify pull page retry",
|
|
20006
|
+
WAKEUP_PULL_COMPLETED: "WakeupNotify pull completed",
|
|
20007
|
+
WAKEUP_NOTIFICATION_REJECTED: "WakeupNotify notification rejected",
|
|
20008
|
+
WAKEUP_CHUNK_DISPATCHED: "WakeupNotify chunk dispatched",
|
|
20009
|
+
WAKEUP_IN_MEMORY_WORK_DROPPED: "WakeupNotify in-memory work dropped",
|
|
20010
|
+
AI_CONCURRENCY_SNAPSHOT: "AI concurrency snapshot",
|
|
19972
20011
|
// ── error ─────────────────────────────────────────────────────
|
|
19973
20012
|
XMTP_CONNECTION_FAILED: "XMTP connection failed",
|
|
19974
20013
|
CONVERSATIONS_STREAM_FAILED: "conversations.stream failed",
|
|
@@ -20023,6 +20062,7 @@ var init_events = __esm({
|
|
|
20023
20062
|
AI_RUN_TOOL_FAILED: "AI run tool failed",
|
|
20024
20063
|
IPC_FAILED: "IPC failed",
|
|
20025
20064
|
NOTIFY_AGENTS_WAKEUP_FAILED: "Notify agents wakeup failed",
|
|
20065
|
+
WAKEUP_PULL_FAILED: "WakeupNotify pull failed",
|
|
20026
20066
|
OUTBOUND_AGENT_LOOKUP_FAILED: "Outbound agent lookup failed",
|
|
20027
20067
|
OUTBOUND_ELIGIBILITY_CHECK_FAILED: "Outbound eligibility check failed",
|
|
20028
20068
|
OUTBOUND_ELIGIBILITY_BYPASSED: "Outbound eligibility bypassed",
|
|
@@ -20824,6 +20864,15 @@ var init_sentry_logger = __esm({
|
|
|
20824
20864
|
LogEvent.USER_CHANNEL_MESSAGE_DELIVERED,
|
|
20825
20865
|
LogEvent.SYSTEM_NOTIFICATION_RECEIVED,
|
|
20826
20866
|
LogEvent.SYSTEM_NOTIFICATION_ROUTED,
|
|
20867
|
+
// Paginated WakeupNotify recovery (BL-011) + bounded AI concurrency telemetry.
|
|
20868
|
+
LogEvent.WAKEUP_PULL_STARTED,
|
|
20869
|
+
LogEvent.WAKEUP_PULL_PAGE_FETCHED,
|
|
20870
|
+
LogEvent.WAKEUP_PULL_PAGE_RETRY,
|
|
20871
|
+
LogEvent.WAKEUP_PULL_COMPLETED,
|
|
20872
|
+
LogEvent.WAKEUP_NOTIFICATION_REJECTED,
|
|
20873
|
+
LogEvent.WAKEUP_CHUNK_DISPATCHED,
|
|
20874
|
+
LogEvent.WAKEUP_IN_MEMORY_WORK_DROPPED,
|
|
20875
|
+
LogEvent.AI_CONCURRENCY_SNAPSHOT,
|
|
20827
20876
|
LogEvent.HERMES_SESSION_ROUTE_BINDING,
|
|
20828
20877
|
LogEvent.INBOUND_BLOCKED_ADDRESS_MISMATCH,
|
|
20829
20878
|
LogEvent.INBOUND_BLOCKED_INELIGIBLE,
|
|
@@ -25239,7 +25288,7 @@ var require_websocket2 = __commonJS({
|
|
|
25239
25288
|
var http2 = require("http");
|
|
25240
25289
|
var net = require("net");
|
|
25241
25290
|
var tls = require("tls");
|
|
25242
|
-
var { randomBytes: randomBytes4, createHash:
|
|
25291
|
+
var { randomBytes: randomBytes4, createHash: createHash7 } = require("crypto");
|
|
25243
25292
|
var { Duplex, Readable } = require("stream");
|
|
25244
25293
|
var { URL: URL2 } = require("url");
|
|
25245
25294
|
var PerMessageDeflate = require_permessage_deflate();
|
|
@@ -25899,7 +25948,7 @@ var require_websocket2 = __commonJS({
|
|
|
25899
25948
|
abortHandshake(websocket, socket, "Invalid Upgrade header");
|
|
25900
25949
|
return;
|
|
25901
25950
|
}
|
|
25902
|
-
const digest =
|
|
25951
|
+
const digest = createHash7("sha1").update(key + GUID).digest("base64");
|
|
25903
25952
|
if (res.headers["sec-websocket-accept"] !== digest) {
|
|
25904
25953
|
abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
|
|
25905
25954
|
return;
|
|
@@ -26266,7 +26315,7 @@ var require_websocket_server = __commonJS({
|
|
|
26266
26315
|
var EventEmitter2 = require("events");
|
|
26267
26316
|
var http2 = require("http");
|
|
26268
26317
|
var { Duplex } = require("stream");
|
|
26269
|
-
var { createHash:
|
|
26318
|
+
var { createHash: createHash7 } = require("crypto");
|
|
26270
26319
|
var extension = require_extension();
|
|
26271
26320
|
var PerMessageDeflate = require_permessage_deflate();
|
|
26272
26321
|
var subprotocol = require_subprotocol();
|
|
@@ -26567,7 +26616,7 @@ var require_websocket_server = __commonJS({
|
|
|
26567
26616
|
);
|
|
26568
26617
|
}
|
|
26569
26618
|
if (this._state > RUNNING) return abortHandshake(socket, 503);
|
|
26570
|
-
const digest =
|
|
26619
|
+
const digest = createHash7("sha1").update(key + GUID).digest("base64");
|
|
26571
26620
|
const headers = [
|
|
26572
26621
|
"HTTP/1.1 101 Switching Protocols",
|
|
26573
26622
|
"Upgrade: websocket",
|
|
@@ -26932,7 +26981,7 @@ function buildConnectParams(config, instanceId, protocolVersion) {
|
|
|
26932
26981
|
client: {
|
|
26933
26982
|
id: "gateway-client",
|
|
26934
26983
|
displayName: "okx-a2a-node",
|
|
26935
|
-
version: "0.2.
|
|
26984
|
+
version: "0.2.9-beta-912b775358-260824171011",
|
|
26936
26985
|
platform: "node",
|
|
26937
26986
|
mode: "backend",
|
|
26938
26987
|
instanceId
|
|
@@ -26943,7 +26992,7 @@ function buildConnectParams(config, instanceId, protocolVersion) {
|
|
|
26943
26992
|
commands: [],
|
|
26944
26993
|
permissions: {},
|
|
26945
26994
|
locale: Intl.DateTimeFormat().resolvedOptions().locale || "en-US",
|
|
26946
|
-
userAgent: `okx-a2a-node/${"0.2.
|
|
26995
|
+
userAgent: `okx-a2a-node/${"0.2.9-beta-912b775358-260824171011"}`,
|
|
26947
26996
|
auth: {
|
|
26948
26997
|
...config.token ? { token: config.token } : {},
|
|
26949
26998
|
...config.password ? { password: config.password } : {}
|
|
@@ -28910,7 +28959,7 @@ var init_sentry_config = __esm({
|
|
|
28910
28959
|
environment = process.env.SENTRY_ENV === "dev" ? "dev" : "prod";
|
|
28911
28960
|
SENTRY_CONFIG = {
|
|
28912
28961
|
projectName: "okx/openclaw-okx-a2a-extension",
|
|
28913
|
-
release: "0.2.
|
|
28962
|
+
release: "0.2.9-beta-912b775358-260824171011",
|
|
28914
28963
|
environment,
|
|
28915
28964
|
runtimeContainer: normalizeRuntimeContainer(process.env.OKX_A2A_RUNTIME_CONTAINER)
|
|
28916
28965
|
};
|
|
@@ -40080,7 +40129,7 @@ async function exportDiagnosticLogs(options) {
|
|
|
40080
40129
|
node: process.version,
|
|
40081
40130
|
platform: process.platform,
|
|
40082
40131
|
arch: process.arch,
|
|
40083
|
-
packageVersion: true ? "0.2.
|
|
40132
|
+
packageVersion: true ? "0.2.9-beta-912b775358-260824171011" : "unknown",
|
|
40084
40133
|
sensitiveContentIncluded: options.includeSensitiveContent,
|
|
40085
40134
|
listenerAndLlmContentIncluded: true,
|
|
40086
40135
|
credentialsAlwaysRedacted: true,
|
|
@@ -58618,36 +58667,15 @@ var init_xmtp_sdk = __esm({
|
|
|
58618
58667
|
timer
|
|
58619
58668
|
});
|
|
58620
58669
|
}
|
|
58621
|
-
notifyAgentsWakeupAfterReplay() {
|
|
58622
|
-
const notifyAgentsWakeup2 = this.tools.notifyAgentsWakeup;
|
|
58623
|
-
const agentIds = this.allAgents.map((agent) => agent.agentId);
|
|
58624
|
-
if (!notifyAgentsWakeup2 || agentIds.length === 0) {
|
|
58625
|
-
return;
|
|
58626
|
-
}
|
|
58627
|
-
void notifyAgentsWakeup2(agentIds).then(() => {
|
|
58628
|
-
logger.info(LogEvent.AGENTS_WAKEUP_NOTIFIED, {
|
|
58629
|
-
count: String(agentIds.length),
|
|
58630
|
-
onchainosAgentIds: agentIds.join(","),
|
|
58631
|
-
stage: "after-startup-replay"
|
|
58632
|
-
});
|
|
58633
|
-
}).catch((err2) => {
|
|
58634
|
-
logWithTimestamp("[xmtp-sdk] notifyAgentsWakeup unexpected error:", err2);
|
|
58635
|
-
logger.error(
|
|
58636
|
-
LogEvent.NOTIFY_AGENTS_WAKEUP_FAILED,
|
|
58637
|
-
err2 instanceof Error ? err2 : new Error(String(err2)),
|
|
58638
|
-
{
|
|
58639
|
-
count: String(agentIds.length),
|
|
58640
|
-
stage: "after-startup-replay"
|
|
58641
|
-
}
|
|
58642
|
-
);
|
|
58643
|
-
});
|
|
58644
|
-
}
|
|
58645
58670
|
/**
|
|
58646
58671
|
* Completes the startup handoff from stored history to the live stream.
|
|
58647
58672
|
* Listeners are already attached, but their host handlers stay buffered
|
|
58648
|
-
* until replay finishes and the buffer is drained.
|
|
58649
|
-
*
|
|
58650
|
-
*
|
|
58673
|
+
* until replay finishes and the buffer is drained.
|
|
58674
|
+
*
|
|
58675
|
+
* Telling the backend the agents are awake is deliberately NOT done here.
|
|
58676
|
+
* The daemon (listener.ts) runs the paginated task-wakeup pull AFTER the bounded
|
|
58677
|
+
* command processor is ready, so wakeup-triggered work cannot be dispatched
|
|
58678
|
+
* before the processor exists.
|
|
58651
58679
|
*/
|
|
58652
58680
|
async completeStartupReplay() {
|
|
58653
58681
|
const startupGates = new Map(
|
|
@@ -58662,7 +58690,6 @@ var init_xmtp_sdk = __esm({
|
|
|
58662
58690
|
}
|
|
58663
58691
|
this.resolveStartupReplayCompletion?.();
|
|
58664
58692
|
this.resolveStartupReplayCompletion = void 0;
|
|
58665
|
-
this.notifyAgentsWakeupAfterReplay();
|
|
58666
58693
|
return summary;
|
|
58667
58694
|
}
|
|
58668
58695
|
async startListeningForAddresses(addresses) {
|
|
@@ -59901,39 +59928,6 @@ function fingerprintAgents(agents) {
|
|
|
59901
59928
|
function filterNoisyAgentIdentityLog(stderr) {
|
|
59902
59929
|
return stderr.split(/\r?\n/).filter((line) => !line.includes("[agent-identity] get response")).join("\n").trim();
|
|
59903
59930
|
}
|
|
59904
|
-
function previewLogText(value, max = 300) {
|
|
59905
|
-
const normalized = value.replace(/\s+/g, " ").trim();
|
|
59906
|
-
return normalized.length > max ? `${normalized.slice(0, max)}...` : normalized;
|
|
59907
|
-
}
|
|
59908
|
-
async function notifyAgentsWakeup(agentIds) {
|
|
59909
|
-
if (agentIds.length === 0) {
|
|
59910
|
-
logWithTimestamp("[onchainos] wakeup-notify: agentIds empty, skipping");
|
|
59911
|
-
return;
|
|
59912
|
-
}
|
|
59913
|
-
const ids = agentIds.join(",");
|
|
59914
|
-
logWithTimestamp(`[onchainos] sending wakeup-notify (agent-ids=${ids})`);
|
|
59915
|
-
try {
|
|
59916
|
-
const { stdout, stderr } = await exec([
|
|
59917
|
-
"agent",
|
|
59918
|
-
"wakeup-notify",
|
|
59919
|
-
"--agent-ids",
|
|
59920
|
-
ids
|
|
59921
|
-
]);
|
|
59922
|
-
if (stderr) {
|
|
59923
|
-
logWithTimestamp(`[onchainos] stderr (wakeup-notify): ${stderr}`);
|
|
59924
|
-
}
|
|
59925
|
-
logWithTimestamp(
|
|
59926
|
-
`[onchainos] wakeup-notify result agentIds=${ids} stdoutBytes=${Buffer.byteLength(stdout ?? "", "utf8")} stdoutPreview=${previewLogText(stdout ?? "")}`
|
|
59927
|
-
);
|
|
59928
|
-
logWithTimestamp(`[onchainos] wakeup-notify succeeded (agent-ids=${ids})`);
|
|
59929
|
-
} catch (err2) {
|
|
59930
|
-
guardCatchSessionExpired2(err2, "wakeup-notify");
|
|
59931
|
-
logWithTimestamp(
|
|
59932
|
-
`[onchainos] wakeup-notify failed (agent-ids=${ids}):`,
|
|
59933
|
-
err2?.message ?? err2
|
|
59934
|
-
);
|
|
59935
|
-
}
|
|
59936
|
-
}
|
|
59937
59931
|
async function sendHeartbeat(chainIndex) {
|
|
59938
59932
|
logWithTimestamp(`[onchainos] sending heartbeat (chain-index=${chainIndex})`);
|
|
59939
59933
|
try {
|
|
@@ -65195,6 +65189,29 @@ var init_xmtp_debug = __esm({
|
|
|
65195
65189
|
}
|
|
65196
65190
|
});
|
|
65197
65191
|
|
|
65192
|
+
// src/ai-concurrency-config.ts
|
|
65193
|
+
function resolveMaxActiveAiExecutions(env = process.env) {
|
|
65194
|
+
const raw = env.OKX_A2A_MAX_ACTIVE_AI_EXECUTIONS ?? env.OKX_AGENT_TASK_MAX_ACTIVE_AI_EXECUTIONS;
|
|
65195
|
+
if (raw === void 0 || raw.trim() === "") {
|
|
65196
|
+
return { limit: DEFAULT_MAX_ACTIVE_AI_EXECUTIONS, anomaly: null };
|
|
65197
|
+
}
|
|
65198
|
+
const parsed = Number(raw);
|
|
65199
|
+
if (Number.isFinite(parsed) && Number.isInteger(parsed) && parsed > 0) {
|
|
65200
|
+
return { limit: parsed, anomaly: null };
|
|
65201
|
+
}
|
|
65202
|
+
return {
|
|
65203
|
+
limit: DEFAULT_MAX_ACTIVE_AI_EXECUTIONS,
|
|
65204
|
+
anomaly: `invalid value "${raw}", using default ${DEFAULT_MAX_ACTIVE_AI_EXECUTIONS}`
|
|
65205
|
+
};
|
|
65206
|
+
}
|
|
65207
|
+
var DEFAULT_MAX_ACTIVE_AI_EXECUTIONS;
|
|
65208
|
+
var init_ai_concurrency_config = __esm({
|
|
65209
|
+
"src/ai-concurrency-config.ts"() {
|
|
65210
|
+
"use strict";
|
|
65211
|
+
DEFAULT_MAX_ACTIVE_AI_EXECUTIONS = 4;
|
|
65212
|
+
}
|
|
65213
|
+
});
|
|
65214
|
+
|
|
65198
65215
|
// src/command-processor.ts
|
|
65199
65216
|
function commandSentryExtra(command, extra = {}) {
|
|
65200
65217
|
const base = {
|
|
@@ -65244,6 +65261,17 @@ function startCommandProcessor(params) {
|
|
|
65244
65261
|
const executionTimeoutMs = readPositiveEnv("OKX_A2A_COMMAND_EXECUTION_TIMEOUT_MS", DEFAULT_COMMAND_EXECUTION_TIMEOUT_MS);
|
|
65245
65262
|
const staleTimeoutMs = readPositiveEnv("OKX_A2A_COMMAND_STALE_TIMEOUT_MS", DEFAULT_COMMAND_STALE_TIMEOUT_MS);
|
|
65246
65263
|
const aiStaleTimeoutMs = readPositiveEnv("OKX_A2A_AI_COMMAND_STALE_TIMEOUT_MS", DEFAULT_AI_COMMAND_STALE_TIMEOUT_MS);
|
|
65264
|
+
const { limit: maxActiveAiExecutions, anomaly: aiLimitAnomaly } = resolveMaxActiveAiExecutions(process.env);
|
|
65265
|
+
if (aiLimitAnomaly) {
|
|
65266
|
+
logWithTimestamp(`[okx-agent-task] AI concurrency limit config anomaly: ${aiLimitAnomaly}`);
|
|
65267
|
+
logger.info(LogEvent.AI_CONCURRENCY_SNAPSHOT, {
|
|
65268
|
+
component: "node_command_processor",
|
|
65269
|
+
stage: "config",
|
|
65270
|
+
reason: "invalid_config_using_default",
|
|
65271
|
+
configuredLimit: String(maxActiveAiExecutions),
|
|
65272
|
+
anomaly: aiLimitAnomaly
|
|
65273
|
+
});
|
|
65274
|
+
}
|
|
65247
65275
|
let inFlight = false;
|
|
65248
65276
|
let aiScanInFlight = false;
|
|
65249
65277
|
const activeAiQueueKeys = /* @__PURE__ */ new Set();
|
|
@@ -65333,6 +65361,9 @@ function startCommandProcessor(params) {
|
|
|
65333
65361
|
inFlight = false;
|
|
65334
65362
|
}
|
|
65335
65363
|
};
|
|
65364
|
+
const AI_SNAPSHOT_MIN_INTERVAL_MS = 15e3;
|
|
65365
|
+
let lastAiSnapshotSignature = "";
|
|
65366
|
+
let lastAiSnapshotAtMs = 0;
|
|
65336
65367
|
const aiTick = async () => {
|
|
65337
65368
|
if (aiScanInFlight) {
|
|
65338
65369
|
return;
|
|
@@ -65345,15 +65376,33 @@ function startCommandProcessor(params) {
|
|
|
65345
65376
|
skipCommandIds: activeAiCommandIds
|
|
65346
65377
|
});
|
|
65347
65378
|
const pending = await commands.listPendingEntries();
|
|
65379
|
+
const pendingAi = pending.filter((entry) => isAiDispatchCommand(entry.command));
|
|
65380
|
+
if (activeAiCommandIds.size > 0 || pendingAi.length > 0) {
|
|
65381
|
+
const snapshotNow = Date.now();
|
|
65382
|
+
const oldestQueuedAgeMs = pendingAi.reduce((oldest, entry) => {
|
|
65383
|
+
const createdAt = Number.isFinite(entry.command.createdAt) ? entry.command.createdAt : entry.mtimeMs;
|
|
65384
|
+
return Math.max(oldest, snapshotNow - createdAt);
|
|
65385
|
+
}, 0);
|
|
65386
|
+
const snapshotSignature = `${maxActiveAiExecutions}|${activeAiCommandIds.size}|${pendingAi.length}`;
|
|
65387
|
+
if (snapshotSignature !== lastAiSnapshotSignature || snapshotNow - lastAiSnapshotAtMs >= AI_SNAPSHOT_MIN_INTERVAL_MS) {
|
|
65388
|
+
lastAiSnapshotSignature = snapshotSignature;
|
|
65389
|
+
lastAiSnapshotAtMs = snapshotNow;
|
|
65390
|
+
logger.info(LogEvent.AI_CONCURRENCY_SNAPSHOT, {
|
|
65391
|
+
component: "node_command_processor",
|
|
65392
|
+
configuredLimit: String(maxActiveAiExecutions),
|
|
65393
|
+
activeCount: String(activeAiCommandIds.size),
|
|
65394
|
+
queueDepth: String(pendingAi.length),
|
|
65395
|
+
oldestQueuedAgeMs: String(oldestQueuedAgeMs)
|
|
65396
|
+
});
|
|
65397
|
+
}
|
|
65398
|
+
} else {
|
|
65399
|
+
lastAiSnapshotSignature = "";
|
|
65400
|
+
}
|
|
65348
65401
|
for (const entry of pending) {
|
|
65349
65402
|
const command = entry.command;
|
|
65350
65403
|
if (!isAiDispatchCommand(command)) {
|
|
65351
65404
|
continue;
|
|
65352
65405
|
}
|
|
65353
|
-
const queueKey = buildAiCommandQueueKey(command);
|
|
65354
|
-
if (activeAiQueueKeys.has(queueKey)) {
|
|
65355
|
-
continue;
|
|
65356
|
-
}
|
|
65357
65406
|
if (isStalePending(entry, aiStaleTimeoutMs)) {
|
|
65358
65407
|
const message = `${command.type}/${command.kind} command expired after ${formatDuration2(Date.now() - command.createdAt)} in pending queue`;
|
|
65359
65408
|
await commands.completePending(command, {
|
|
@@ -65364,13 +65413,20 @@ function startCommandProcessor(params) {
|
|
|
65364
65413
|
stage: "pending",
|
|
65365
65414
|
ageMs: Date.now() - command.createdAt,
|
|
65366
65415
|
timeoutMs: aiStaleTimeoutMs,
|
|
65367
|
-
reason: "
|
|
65416
|
+
reason: "queue_expired"
|
|
65368
65417
|
}));
|
|
65369
65418
|
logWithTimestamp(
|
|
65370
65419
|
`[okx-agent-task] ${command.type}/${command.kind} command expired id=${command.id}: ${message}`
|
|
65371
65420
|
);
|
|
65372
65421
|
continue;
|
|
65373
65422
|
}
|
|
65423
|
+
if (activeAiCommandIds.size >= maxActiveAiExecutions) {
|
|
65424
|
+
continue;
|
|
65425
|
+
}
|
|
65426
|
+
const queueKey = buildAiCommandQueueKey(command);
|
|
65427
|
+
if (activeAiQueueKeys.has(queueKey)) {
|
|
65428
|
+
continue;
|
|
65429
|
+
}
|
|
65374
65430
|
const processingPath = await commands.take(command);
|
|
65375
65431
|
if (!processingPath) {
|
|
65376
65432
|
continue;
|
|
@@ -65943,6 +65999,9 @@ function isStalePending(entry, staleTimeoutMs) {
|
|
|
65943
65999
|
return Date.now() - createdAt > staleTimeoutMs;
|
|
65944
66000
|
}
|
|
65945
66001
|
function buildAiCommandQueueKey(command) {
|
|
66002
|
+
if (command.jobId) {
|
|
66003
|
+
return `job:${command.jobId}`;
|
|
66004
|
+
}
|
|
65946
66005
|
if (command.kind === "job-message") {
|
|
65947
66006
|
return buildDispatchSessionKey(command.jobId, command.sessionAgentId);
|
|
65948
66007
|
}
|
|
@@ -66050,6 +66109,7 @@ var init_command_processor = __esm({
|
|
|
66050
66109
|
init_user_attention_ipc();
|
|
66051
66110
|
init_sentry_logger();
|
|
66052
66111
|
init_xmtp_debug();
|
|
66112
|
+
init_ai_concurrency_config();
|
|
66053
66113
|
DEFAULT_COMMAND_EXECUTION_TIMEOUT_MS = 5e4;
|
|
66054
66114
|
DEFAULT_COMMAND_STALE_TIMEOUT_MS = 12e4;
|
|
66055
66115
|
DEFAULT_AI_COMMAND_STALE_TIMEOUT_MS = 30 * 6e4;
|
|
@@ -67650,6 +67710,575 @@ var init_message_handler = __esm({
|
|
|
67650
67710
|
}
|
|
67651
67711
|
});
|
|
67652
67712
|
|
|
67713
|
+
// src/wakeup-notify-client.ts
|
|
67714
|
+
function isTransientTransportError(err2) {
|
|
67715
|
+
const message = err2 instanceof Error ? err2.message : String(err2);
|
|
67716
|
+
return TRANSIENT_TRANSPORT_PATTERN.test(message);
|
|
67717
|
+
}
|
|
67718
|
+
function isPlainObject4(value) {
|
|
67719
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
67720
|
+
}
|
|
67721
|
+
function isValidWakeupItem(raw) {
|
|
67722
|
+
if (!isPlainObject4(raw)) {
|
|
67723
|
+
return { ok: false, reason: "malformed_item" };
|
|
67724
|
+
}
|
|
67725
|
+
if (typeof raw.agentId !== "string" || raw.agentId.length === 0) {
|
|
67726
|
+
return { ok: false, reason: "missing_agent_id" };
|
|
67727
|
+
}
|
|
67728
|
+
const message = raw.message;
|
|
67729
|
+
if (!isPlainObject4(message) || message.source !== "system") {
|
|
67730
|
+
return { ok: false, reason: "not_system_notification" };
|
|
67731
|
+
}
|
|
67732
|
+
if (message.event !== "wakeup_notify") {
|
|
67733
|
+
return { ok: false, reason: "not_wakeup_notify" };
|
|
67734
|
+
}
|
|
67735
|
+
return {
|
|
67736
|
+
ok: true,
|
|
67737
|
+
item: { agentId: raw.agentId, message }
|
|
67738
|
+
};
|
|
67739
|
+
}
|
|
67740
|
+
function canonicalize(value) {
|
|
67741
|
+
if (Array.isArray(value)) {
|
|
67742
|
+
return value.map(canonicalize);
|
|
67743
|
+
}
|
|
67744
|
+
if (value && typeof value === "object") {
|
|
67745
|
+
const source = value;
|
|
67746
|
+
return Object.keys(source).sort().reduce((acc, key) => {
|
|
67747
|
+
acc[key] = canonicalize(source[key]);
|
|
67748
|
+
return acc;
|
|
67749
|
+
}, {});
|
|
67750
|
+
}
|
|
67751
|
+
return value;
|
|
67752
|
+
}
|
|
67753
|
+
function deriveWakeupDedupeKey(item) {
|
|
67754
|
+
const canonicalMessage = JSON.stringify(canonicalize(item.message ?? {}));
|
|
67755
|
+
const identity = `${item.agentId}
|
|
67756
|
+
${canonicalMessage}`;
|
|
67757
|
+
return `wakeup:${(0, import_node_crypto15.createHash)("sha256").update(identity).digest("hex").slice(0, 24)}`;
|
|
67758
|
+
}
|
|
67759
|
+
async function fetchAllWakeupNotifications(opts) {
|
|
67760
|
+
const { agentIds, fetchPage, onPage } = opts;
|
|
67761
|
+
const maxPages = opts.maxPages;
|
|
67762
|
+
const maxPageAttempts = opts.maxPageAttempts ?? DEFAULT_MAX_PAGE_ATTEMPTS;
|
|
67763
|
+
const retryDelayMs = opts.retryDelayMs ?? DEFAULT_PAGE_RETRY_DELAY_MS;
|
|
67764
|
+
const sleep5 = opts.sleep ?? ((ms) => new Promise((resolve14) => setTimeout(resolve14, ms)));
|
|
67765
|
+
const isRetryableError = opts.isRetryableError ?? isTransientTransportError;
|
|
67766
|
+
const onRetry = opts.onRetry;
|
|
67767
|
+
const fetchPageWithRetry = async (pageNum) => {
|
|
67768
|
+
let attempt = 0;
|
|
67769
|
+
while (true) {
|
|
67770
|
+
attempt++;
|
|
67771
|
+
try {
|
|
67772
|
+
return await fetchPage({ agentIds, page: pageNum });
|
|
67773
|
+
} catch (err2) {
|
|
67774
|
+
if (!isRetryableError(err2) || attempt >= maxPageAttempts) {
|
|
67775
|
+
throw err2;
|
|
67776
|
+
}
|
|
67777
|
+
onRetry?.({ page: pageNum, attempt, reason: "transient_transport" });
|
|
67778
|
+
await sleep5(retryDelayMs * attempt + Math.floor(Math.random() * (retryDelayMs + 1)));
|
|
67779
|
+
}
|
|
67780
|
+
}
|
|
67781
|
+
};
|
|
67782
|
+
const items = [];
|
|
67783
|
+
const rejects = [];
|
|
67784
|
+
const visited = /* @__PURE__ */ new Set();
|
|
67785
|
+
let pagesFetched = 0;
|
|
67786
|
+
let page = 1;
|
|
67787
|
+
let terminated = "empty";
|
|
67788
|
+
try {
|
|
67789
|
+
while (true) {
|
|
67790
|
+
const resp = await fetchPageWithRetry(page);
|
|
67791
|
+
pagesFetched++;
|
|
67792
|
+
if (resp.code !== 0) {
|
|
67793
|
+
terminated = "business_error";
|
|
67794
|
+
break;
|
|
67795
|
+
}
|
|
67796
|
+
const rawList = resp.data?.list;
|
|
67797
|
+
if (!Array.isArray(rawList)) {
|
|
67798
|
+
rejects.push({ reason: "invalid_response_list" });
|
|
67799
|
+
terminated = "invalid_response";
|
|
67800
|
+
break;
|
|
67801
|
+
}
|
|
67802
|
+
const list = rawList;
|
|
67803
|
+
let itemCount = 0;
|
|
67804
|
+
let rejectedCount = 0;
|
|
67805
|
+
for (const element of list) {
|
|
67806
|
+
const check = isValidWakeupItem(element);
|
|
67807
|
+
if (check.ok) {
|
|
67808
|
+
items.push(check.item);
|
|
67809
|
+
itemCount++;
|
|
67810
|
+
} else {
|
|
67811
|
+
rejects.push({ reason: check.reason });
|
|
67812
|
+
rejectedCount++;
|
|
67813
|
+
}
|
|
67814
|
+
}
|
|
67815
|
+
const nextPage = resp.data?.nextPage;
|
|
67816
|
+
onPage?.({ page, itemCount, rejectedCount, hasNextPage: nextPage != null });
|
|
67817
|
+
if (nextPage === null) {
|
|
67818
|
+
terminated = items.length || rejects.length ? "next_page_null" : "empty";
|
|
67819
|
+
break;
|
|
67820
|
+
}
|
|
67821
|
+
if (typeof nextPage !== "number" || !Number.isInteger(nextPage) || nextPage <= 0) {
|
|
67822
|
+
rejects.push({ reason: "invalid_next_page" });
|
|
67823
|
+
terminated = "invalid_response";
|
|
67824
|
+
break;
|
|
67825
|
+
}
|
|
67826
|
+
visited.add(page);
|
|
67827
|
+
page = nextPage;
|
|
67828
|
+
if (visited.has(page) || maxPages !== void 0 && pagesFetched >= maxPages) {
|
|
67829
|
+
terminated = "max_pages";
|
|
67830
|
+
break;
|
|
67831
|
+
}
|
|
67832
|
+
}
|
|
67833
|
+
} catch {
|
|
67834
|
+
terminated = "transport_error";
|
|
67835
|
+
}
|
|
67836
|
+
const summary = {
|
|
67837
|
+
pagesFetched,
|
|
67838
|
+
received: items.length + rejects.length,
|
|
67839
|
+
persisted: 0,
|
|
67840
|
+
partial: 0,
|
|
67841
|
+
duplicates: 0,
|
|
67842
|
+
rejected: rejects.length,
|
|
67843
|
+
terminated
|
|
67844
|
+
};
|
|
67845
|
+
return { items, summary, rejects };
|
|
67846
|
+
}
|
|
67847
|
+
var import_node_crypto15, DEFAULT_MAX_PAGE_ATTEMPTS, DEFAULT_PAGE_RETRY_DELAY_MS, TRANSIENT_TRANSPORT_PATTERN;
|
|
67848
|
+
var init_wakeup_notify_client = __esm({
|
|
67849
|
+
"src/wakeup-notify-client.ts"() {
|
|
67850
|
+
"use strict";
|
|
67851
|
+
import_node_crypto15 = require("node:crypto");
|
|
67852
|
+
DEFAULT_MAX_PAGE_ATTEMPTS = 3;
|
|
67853
|
+
DEFAULT_PAGE_RETRY_DELAY_MS = 500;
|
|
67854
|
+
TRANSIENT_TRANSPORT_PATTERN = /timed out|timeout|ETIMEDOUT|ECONNRESET|ECONNREFUSED|ENOTFOUND|EAI_AGAIN|socket hang up|network/i;
|
|
67855
|
+
}
|
|
67856
|
+
});
|
|
67857
|
+
|
|
67858
|
+
// src/wakeup-notify-ingest.ts
|
|
67859
|
+
async function ingestWakeupNotification(item, deps) {
|
|
67860
|
+
const messageId = deriveWakeupDedupeKey(item);
|
|
67861
|
+
const itemJobId = item.message.jobId ?? null;
|
|
67862
|
+
const rawText = JSON.stringify({ agentId: item.agentId, message: item.message });
|
|
67863
|
+
const notif = extractSystemNotification(JSON.parse(rawText));
|
|
67864
|
+
if (!notif?.agentId) {
|
|
67865
|
+
return {
|
|
67866
|
+
status: "rejected",
|
|
67867
|
+
reason: "invalid_system_notification",
|
|
67868
|
+
dedupeKey: messageId,
|
|
67869
|
+
jobId: itemJobId,
|
|
67870
|
+
targetCount: 0
|
|
67871
|
+
};
|
|
67872
|
+
}
|
|
67873
|
+
const targets = resolveSystemNotificationTargets(
|
|
67874
|
+
{ sessionStore: deps.sessionStore, myXmtpAddress: deps.myXmtpAddress ?? "", store: void 0 },
|
|
67875
|
+
notif
|
|
67876
|
+
);
|
|
67877
|
+
let succeeded = 0;
|
|
67878
|
+
let failed = 0;
|
|
67879
|
+
for (const target of targets) {
|
|
67880
|
+
let enqueued = false;
|
|
67881
|
+
for (let attempt = 1; attempt <= MAX_TARGET_ENQUEUE_ATTEMPTS && !enqueued; attempt++) {
|
|
67882
|
+
try {
|
|
67883
|
+
await enqueueAiSessionMessageDispatch({
|
|
67884
|
+
commands: deps.commands,
|
|
67885
|
+
event: {
|
|
67886
|
+
sessionKey: target.sessionKey,
|
|
67887
|
+
content: rawText,
|
|
67888
|
+
messageId,
|
|
67889
|
+
jobId: target.jobId ?? null,
|
|
67890
|
+
agentId: target.agentId ?? null
|
|
67891
|
+
}
|
|
67892
|
+
});
|
|
67893
|
+
enqueued = true;
|
|
67894
|
+
} catch {
|
|
67895
|
+
}
|
|
67896
|
+
}
|
|
67897
|
+
if (enqueued) {
|
|
67898
|
+
succeeded += 1;
|
|
67899
|
+
} else {
|
|
67900
|
+
failed += 1;
|
|
67901
|
+
}
|
|
67902
|
+
}
|
|
67903
|
+
if (targets.length > 0 && succeeded === 0) {
|
|
67904
|
+
return {
|
|
67905
|
+
status: "rejected",
|
|
67906
|
+
reason: "enqueue_failed",
|
|
67907
|
+
dedupeKey: messageId,
|
|
67908
|
+
jobId: notif.jobId ?? null,
|
|
67909
|
+
targetCount: 0,
|
|
67910
|
+
failedTargetCount: failed
|
|
67911
|
+
};
|
|
67912
|
+
}
|
|
67913
|
+
if (failed > 0) {
|
|
67914
|
+
return {
|
|
67915
|
+
status: "partial",
|
|
67916
|
+
reason: "partial_enqueue",
|
|
67917
|
+
dedupeKey: messageId,
|
|
67918
|
+
jobId: notif.jobId ?? null,
|
|
67919
|
+
targetCount: succeeded,
|
|
67920
|
+
failedTargetCount: failed
|
|
67921
|
+
};
|
|
67922
|
+
}
|
|
67923
|
+
return {
|
|
67924
|
+
status: "persisted",
|
|
67925
|
+
dedupeKey: messageId,
|
|
67926
|
+
jobId: notif.jobId ?? null,
|
|
67927
|
+
targetCount: succeeded
|
|
67928
|
+
};
|
|
67929
|
+
}
|
|
67930
|
+
var MAX_TARGET_ENQUEUE_ATTEMPTS;
|
|
67931
|
+
var init_wakeup_notify_ingest = __esm({
|
|
67932
|
+
"src/wakeup-notify-ingest.ts"() {
|
|
67933
|
+
"use strict";
|
|
67934
|
+
init_ai_dispatch_queue();
|
|
67935
|
+
init_message_handler();
|
|
67936
|
+
init_wakeup_notify_client();
|
|
67937
|
+
MAX_TARGET_ENQUEUE_ATTEMPTS = 3;
|
|
67938
|
+
}
|
|
67939
|
+
});
|
|
67940
|
+
|
|
67941
|
+
// src/wakeup-notify-transport.ts
|
|
67942
|
+
function withTimeout3(promise, timeoutMs, label) {
|
|
67943
|
+
return new Promise((resolve14, reject) => {
|
|
67944
|
+
const timer = setTimeout(() => {
|
|
67945
|
+
reject(new Error(`${label} timed out after ${timeoutMs}ms`));
|
|
67946
|
+
}, timeoutMs);
|
|
67947
|
+
promise.then(
|
|
67948
|
+
(value) => {
|
|
67949
|
+
clearTimeout(timer);
|
|
67950
|
+
resolve14(value);
|
|
67951
|
+
},
|
|
67952
|
+
(err2) => {
|
|
67953
|
+
clearTimeout(timer);
|
|
67954
|
+
reject(err2);
|
|
67955
|
+
}
|
|
67956
|
+
);
|
|
67957
|
+
});
|
|
67958
|
+
}
|
|
67959
|
+
function resolveCliTimeoutMs(override) {
|
|
67960
|
+
if (typeof override === "number" && Number.isFinite(override) && override > 0) {
|
|
67961
|
+
return override;
|
|
67962
|
+
}
|
|
67963
|
+
const raw = Number(process.env.OKX_A2A_WAKEUP_CLI_TIMEOUT_MS);
|
|
67964
|
+
return Number.isFinite(raw) && raw > 0 ? raw : DEFAULT_CLI_TIMEOUT_MS;
|
|
67965
|
+
}
|
|
67966
|
+
function isPlainObject5(value) {
|
|
67967
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
67968
|
+
}
|
|
67969
|
+
function mapCliStdoutToWakeupResponse(parsed) {
|
|
67970
|
+
const root = isPlainObject5(parsed) ? parsed : {};
|
|
67971
|
+
const rootData = isPlainObject5(root.data) ? root.data : {};
|
|
67972
|
+
const nestedData = isPlainObject5(rootData.data) ? rootData.data : {};
|
|
67973
|
+
const candidates = [root, rootData, nestedData];
|
|
67974
|
+
let code;
|
|
67975
|
+
let msg;
|
|
67976
|
+
let list = [];
|
|
67977
|
+
let listFound = false;
|
|
67978
|
+
let nextPage = null;
|
|
67979
|
+
let nextPageFound = false;
|
|
67980
|
+
for (const candidate of candidates) {
|
|
67981
|
+
if (code === void 0 && typeof candidate.code === "number" && Number.isFinite(candidate.code)) {
|
|
67982
|
+
code = candidate.code;
|
|
67983
|
+
}
|
|
67984
|
+
if (msg === void 0 && typeof candidate.msg === "string") {
|
|
67985
|
+
msg = candidate.msg;
|
|
67986
|
+
}
|
|
67987
|
+
if (!listFound && Array.isArray(candidate.list)) {
|
|
67988
|
+
list = candidate.list;
|
|
67989
|
+
listFound = true;
|
|
67990
|
+
}
|
|
67991
|
+
if (!nextPageFound && "nextPage" in candidate) {
|
|
67992
|
+
const raw = candidate.nextPage;
|
|
67993
|
+
if (typeof raw === "number" && Number.isFinite(raw)) {
|
|
67994
|
+
nextPage = raw;
|
|
67995
|
+
nextPageFound = true;
|
|
67996
|
+
} else if (raw === null) {
|
|
67997
|
+
nextPage = null;
|
|
67998
|
+
nextPageFound = true;
|
|
67999
|
+
}
|
|
68000
|
+
}
|
|
68001
|
+
}
|
|
68002
|
+
if (code === void 0) {
|
|
68003
|
+
code = root.ok === true ? 0 : 1;
|
|
68004
|
+
}
|
|
68005
|
+
return {
|
|
68006
|
+
code,
|
|
68007
|
+
msg,
|
|
68008
|
+
data: { list: listFound ? list : void 0, nextPage: nextPageFound ? nextPage : void 0 }
|
|
68009
|
+
};
|
|
68010
|
+
}
|
|
68011
|
+
function createOnchainosWakeupFetchPage(deps = {}) {
|
|
68012
|
+
const timeoutMs = resolveCliTimeoutMs(deps.timeoutMs);
|
|
68013
|
+
const exec2 = deps.exec ?? ((args) => exec(args, { timeoutMs }));
|
|
68014
|
+
return async ({ agentIds, page }) => {
|
|
68015
|
+
const { stdout } = await withTimeout3(
|
|
68016
|
+
exec2([
|
|
68017
|
+
"agent",
|
|
68018
|
+
TASK_WAKEUP_CLI_COMMAND,
|
|
68019
|
+
"--agent-ids",
|
|
68020
|
+
agentIds.join(","),
|
|
68021
|
+
"--page",
|
|
68022
|
+
String(page)
|
|
68023
|
+
]),
|
|
68024
|
+
timeoutMs,
|
|
68025
|
+
`onchainos ${TASK_WAKEUP_CLI_COMMAND}`
|
|
68026
|
+
);
|
|
68027
|
+
const parsed = parseCliJson(stdout, TASK_WAKEUP_CLI_COMMAND, {
|
|
68028
|
+
page: String(page)
|
|
68029
|
+
});
|
|
68030
|
+
return mapCliStdoutToWakeupResponse(parsed);
|
|
68031
|
+
};
|
|
68032
|
+
}
|
|
68033
|
+
var TASK_WAKEUP_CLI_COMMAND, DEFAULT_CLI_TIMEOUT_MS;
|
|
68034
|
+
var init_wakeup_notify_transport = __esm({
|
|
68035
|
+
"src/wakeup-notify-transport.ts"() {
|
|
68036
|
+
"use strict";
|
|
68037
|
+
init_bin();
|
|
68038
|
+
init_cli_response();
|
|
68039
|
+
TASK_WAKEUP_CLI_COMMAND = "task-wakeup";
|
|
68040
|
+
DEFAULT_CLI_TIMEOUT_MS = 3e4;
|
|
68041
|
+
}
|
|
68042
|
+
});
|
|
68043
|
+
|
|
68044
|
+
// src/wakeup-chunk-config.ts
|
|
68045
|
+
function resolveWakeupChunkSize(env = process.env) {
|
|
68046
|
+
const fallback = resolveMaxActiveAiExecutions(env).limit;
|
|
68047
|
+
const raw = env.OKX_A2A_WAKEUP_CHUNK_SIZE;
|
|
68048
|
+
if (raw === void 0 || raw.trim() === "") {
|
|
68049
|
+
return { chunkSize: fallback, anomaly: null };
|
|
68050
|
+
}
|
|
68051
|
+
const parsed = Number(raw);
|
|
68052
|
+
if (Number.isFinite(parsed) && Number.isInteger(parsed) && parsed > 0) {
|
|
68053
|
+
return { chunkSize: parsed, anomaly: null };
|
|
68054
|
+
}
|
|
68055
|
+
return {
|
|
68056
|
+
chunkSize: fallback,
|
|
68057
|
+
anomaly: `invalid value "${raw}", using default ${fallback}`
|
|
68058
|
+
};
|
|
68059
|
+
}
|
|
68060
|
+
var init_wakeup_chunk_config = __esm({
|
|
68061
|
+
"src/wakeup-chunk-config.ts"() {
|
|
68062
|
+
"use strict";
|
|
68063
|
+
init_ai_concurrency_config();
|
|
68064
|
+
}
|
|
68065
|
+
});
|
|
68066
|
+
|
|
68067
|
+
// src/wakeup-pull.ts
|
|
68068
|
+
function splitIntoChunks(items, size3) {
|
|
68069
|
+
const chunkSize = Math.max(1, size3);
|
|
68070
|
+
const chunks = [];
|
|
68071
|
+
for (let i = 0; i < items.length; i += chunkSize) {
|
|
68072
|
+
chunks.push(items.slice(i, i + chunkSize));
|
|
68073
|
+
}
|
|
68074
|
+
return chunks;
|
|
68075
|
+
}
|
|
68076
|
+
function buildDroppedWorkTelemetry(snapshot) {
|
|
68077
|
+
return {
|
|
68078
|
+
sentry: {
|
|
68079
|
+
component: "wakeup_pull",
|
|
68080
|
+
reason: "daemon_shutdown",
|
|
68081
|
+
remainingChunks: String(snapshot.remainingChunks),
|
|
68082
|
+
droppedMessages: String(snapshot.droppedMessages),
|
|
68083
|
+
affectedJobCount: String(snapshot.pendingJobIds.length),
|
|
68084
|
+
inFlightChunk: String(snapshot.inFlightChunk)
|
|
68085
|
+
},
|
|
68086
|
+
local: {
|
|
68087
|
+
droppedMessages: snapshot.droppedMessages,
|
|
68088
|
+
pendingJobIds: snapshot.pendingJobIds.slice(0, MAX_LOGGED_PENDING_JOB_IDS),
|
|
68089
|
+
jobIdsTruncated: snapshot.pendingJobIds.length > MAX_LOGGED_PENDING_JOB_IDS,
|
|
68090
|
+
inFlightChunk: snapshot.inFlightChunk
|
|
68091
|
+
}
|
|
68092
|
+
};
|
|
68093
|
+
}
|
|
68094
|
+
function logDroppedWakeupWorkOnShutdown(dispatcher) {
|
|
68095
|
+
if (!dispatcher) {
|
|
68096
|
+
return;
|
|
68097
|
+
}
|
|
68098
|
+
const snapshot = dispatcher.pendingSnapshot();
|
|
68099
|
+
if (snapshot.droppedMessages === 0 && !snapshot.inFlightChunk) {
|
|
68100
|
+
return;
|
|
68101
|
+
}
|
|
68102
|
+
const telemetry = buildDroppedWorkTelemetry(snapshot);
|
|
68103
|
+
logger.info(LogEvent.WAKEUP_IN_MEMORY_WORK_DROPPED, telemetry.sentry);
|
|
68104
|
+
logWithTimestamp("[okx-agent-task] WakeupNotify messages dropped on shutdown", telemetry.local);
|
|
68105
|
+
}
|
|
68106
|
+
async function startWakeupNotifyPull(opts) {
|
|
68107
|
+
const enabled = opts.enabled ?? true;
|
|
68108
|
+
const fetchPage = opts.fetchPage ?? (enabled ? createOnchainosWakeupFetchPage() : void 0);
|
|
68109
|
+
if (!enabled || !fetchPage) {
|
|
68110
|
+
logWithTimestamp("[okx-agent-task] WakeupNotify pull skipped (disabled)");
|
|
68111
|
+
return null;
|
|
68112
|
+
}
|
|
68113
|
+
const agentIds = [
|
|
68114
|
+
...new Set(
|
|
68115
|
+
[...opts.service.getClients().keys()].map((addr) => opts.service.getAgentByAddress(addr)?.agentId).filter((id) => typeof id === "string" && id.length > 0)
|
|
68116
|
+
)
|
|
68117
|
+
];
|
|
68118
|
+
if (agentIds.length === 0) {
|
|
68119
|
+
logWithTimestamp("[okx-agent-task] WakeupNotify pull skipped (no active agents)");
|
|
68120
|
+
return null;
|
|
68121
|
+
}
|
|
68122
|
+
logger.info(LogEvent.WAKEUP_PULL_STARTED, {
|
|
68123
|
+
component: "wakeup_pull",
|
|
68124
|
+
agentCount: String(agentIds.length)
|
|
68125
|
+
});
|
|
68126
|
+
const { items, summary, rejects } = await fetchAllWakeupNotifications({
|
|
68127
|
+
agentIds,
|
|
68128
|
+
fetchPage,
|
|
68129
|
+
onPage: (p) => logger.info(LogEvent.WAKEUP_PULL_PAGE_FETCHED, {
|
|
68130
|
+
component: "wakeup_pull",
|
|
68131
|
+
page: String(p.page),
|
|
68132
|
+
itemCount: String(p.itemCount),
|
|
68133
|
+
rejectedCount: String(p.rejectedCount),
|
|
68134
|
+
hasNextPage: String(p.hasNextPage)
|
|
68135
|
+
}),
|
|
68136
|
+
onRetry: (r) => logger.info(LogEvent.WAKEUP_PULL_PAGE_RETRY, {
|
|
68137
|
+
component: "wakeup_pull",
|
|
68138
|
+
page: String(r.page),
|
|
68139
|
+
attempt: String(r.attempt),
|
|
68140
|
+
reason: r.reason
|
|
68141
|
+
})
|
|
68142
|
+
});
|
|
68143
|
+
for (const reject of rejects) {
|
|
68144
|
+
logger.info(LogEvent.WAKEUP_NOTIFICATION_REJECTED, {
|
|
68145
|
+
component: "wakeup_pull",
|
|
68146
|
+
reason: reject.reason
|
|
68147
|
+
});
|
|
68148
|
+
}
|
|
68149
|
+
if (summary.terminated === "transport_error" || summary.terminated === "business_error" || summary.terminated === "invalid_response") {
|
|
68150
|
+
logger.error(LogEvent.WAKEUP_PULL_FAILED, void 0, {
|
|
68151
|
+
component: "wakeup_pull",
|
|
68152
|
+
terminated: summary.terminated
|
|
68153
|
+
});
|
|
68154
|
+
}
|
|
68155
|
+
const resolved = opts.chunkSize != null ? { chunkSize: opts.chunkSize, anomaly: null } : resolveWakeupChunkSize(opts.env);
|
|
68156
|
+
if (resolved.anomaly) {
|
|
68157
|
+
logWithTimestamp(`[okx-agent-task] WakeupNotify chunk size ${resolved.anomaly}`);
|
|
68158
|
+
}
|
|
68159
|
+
const chunks = splitIntoChunks(items, resolved.chunkSize);
|
|
68160
|
+
logger.info(LogEvent.WAKEUP_PULL_COMPLETED, {
|
|
68161
|
+
component: "wakeup_pull",
|
|
68162
|
+
pagesFetched: String(summary.pagesFetched),
|
|
68163
|
+
received: String(summary.received),
|
|
68164
|
+
rejected: String(summary.rejected),
|
|
68165
|
+
chunkCount: String(chunks.length),
|
|
68166
|
+
size: String(resolved.chunkSize),
|
|
68167
|
+
terminated: summary.terminated
|
|
68168
|
+
});
|
|
68169
|
+
const deps = {
|
|
68170
|
+
commands: opts.commands,
|
|
68171
|
+
sessionStore: opts.sessionStore,
|
|
68172
|
+
myXmtpAddress: void 0
|
|
68173
|
+
};
|
|
68174
|
+
const dispatcher = new HeartbeatChunkDispatcher(chunks, deps, opts.shouldContinue);
|
|
68175
|
+
await dispatcher.dispatchNextChunk();
|
|
68176
|
+
return dispatcher.hasPendingChunks() ? dispatcher : null;
|
|
68177
|
+
}
|
|
68178
|
+
var HeartbeatChunkDispatcher, MAX_LOGGED_PENDING_JOB_IDS;
|
|
68179
|
+
var init_wakeup_pull = __esm({
|
|
68180
|
+
"src/wakeup-pull.ts"() {
|
|
68181
|
+
"use strict";
|
|
68182
|
+
init_log();
|
|
68183
|
+
init_sentry_logger();
|
|
68184
|
+
init_wakeup_notify_ingest();
|
|
68185
|
+
init_wakeup_notify_client();
|
|
68186
|
+
init_wakeup_notify_transport();
|
|
68187
|
+
init_wakeup_chunk_config();
|
|
68188
|
+
HeartbeatChunkDispatcher = class {
|
|
68189
|
+
constructor(chunks, deps, shouldContinue) {
|
|
68190
|
+
this.chunks = chunks;
|
|
68191
|
+
this.deps = deps;
|
|
68192
|
+
this.shouldContinue = shouldContinue;
|
|
68193
|
+
}
|
|
68194
|
+
chunks;
|
|
68195
|
+
deps;
|
|
68196
|
+
shouldContinue;
|
|
68197
|
+
index = 0;
|
|
68198
|
+
/** True while a chunk is mid-dispatch (between taking it and its enqueues settling). */
|
|
68199
|
+
dispatching = false;
|
|
68200
|
+
hasPendingChunks() {
|
|
68201
|
+
return this.index < this.chunks.length;
|
|
68202
|
+
}
|
|
68203
|
+
remainingChunks() {
|
|
68204
|
+
return Math.max(0, this.chunks.length - this.index);
|
|
68205
|
+
}
|
|
68206
|
+
/**
|
|
68207
|
+
* Read-only view of the not-yet-started chunks (for shutdown telemetry). `index` has
|
|
68208
|
+
* already advanced past any in-flight chunk, so `chunks.slice(index)` is exactly the work
|
|
68209
|
+
* that has not begun dispatching — the in-flight chunk is excluded from the dropped counts
|
|
68210
|
+
* and reflected only by `inFlightChunk`.
|
|
68211
|
+
*/
|
|
68212
|
+
pendingSnapshot() {
|
|
68213
|
+
const notStarted = this.chunks.slice(this.index);
|
|
68214
|
+
let droppedMessages = 0;
|
|
68215
|
+
const jobIds = /* @__PURE__ */ new Set();
|
|
68216
|
+
for (const chunk of notStarted) {
|
|
68217
|
+
for (const item of chunk) {
|
|
68218
|
+
droppedMessages += 1;
|
|
68219
|
+
const jobId = item.message.jobId;
|
|
68220
|
+
if (typeof jobId === "string" && jobId.length > 0) {
|
|
68221
|
+
jobIds.add(jobId);
|
|
68222
|
+
}
|
|
68223
|
+
}
|
|
68224
|
+
}
|
|
68225
|
+
return {
|
|
68226
|
+
remainingChunks: notStarted.length,
|
|
68227
|
+
droppedMessages,
|
|
68228
|
+
pendingJobIds: [...jobIds],
|
|
68229
|
+
inFlightChunk: this.dispatching
|
|
68230
|
+
};
|
|
68231
|
+
}
|
|
68232
|
+
/** Dispatch the next chunk: enqueue every message in it in parallel. No-op when drained. */
|
|
68233
|
+
async dispatchNextChunk() {
|
|
68234
|
+
if (this.shouldContinue && !this.shouldContinue()) {
|
|
68235
|
+
return;
|
|
68236
|
+
}
|
|
68237
|
+
if (this.index >= this.chunks.length) {
|
|
68238
|
+
return;
|
|
68239
|
+
}
|
|
68240
|
+
const chunk = this.chunks[this.index];
|
|
68241
|
+
this.index += 1;
|
|
68242
|
+
const chunkNumber = this.index;
|
|
68243
|
+
this.dispatching = true;
|
|
68244
|
+
let persisted = 0;
|
|
68245
|
+
let partial = 0;
|
|
68246
|
+
let rejected = 0;
|
|
68247
|
+
try {
|
|
68248
|
+
const outcomes = await Promise.allSettled(
|
|
68249
|
+
chunk.map((item) => ingestWakeupNotification(item, this.deps))
|
|
68250
|
+
);
|
|
68251
|
+
for (const outcome of outcomes) {
|
|
68252
|
+
if (outcome.status === "fulfilled") {
|
|
68253
|
+
if (outcome.value.status === "persisted") {
|
|
68254
|
+
persisted += 1;
|
|
68255
|
+
} else if (outcome.value.status === "partial") {
|
|
68256
|
+
partial += 1;
|
|
68257
|
+
} else {
|
|
68258
|
+
rejected += 1;
|
|
68259
|
+
}
|
|
68260
|
+
} else {
|
|
68261
|
+
rejected += 1;
|
|
68262
|
+
}
|
|
68263
|
+
}
|
|
68264
|
+
} finally {
|
|
68265
|
+
this.dispatching = false;
|
|
68266
|
+
}
|
|
68267
|
+
logger.info(LogEvent.WAKEUP_CHUNK_DISPATCHED, {
|
|
68268
|
+
component: "wakeup_pull",
|
|
68269
|
+
chunk: String(chunkNumber),
|
|
68270
|
+
chunkCount: String(this.chunks.length),
|
|
68271
|
+
size: String(chunk.length),
|
|
68272
|
+
persisted: String(persisted),
|
|
68273
|
+
partial: String(partial),
|
|
68274
|
+
rejected: String(rejected)
|
|
68275
|
+
});
|
|
68276
|
+
}
|
|
68277
|
+
};
|
|
68278
|
+
MAX_LOGGED_PENDING_JOB_IDS = 100;
|
|
68279
|
+
}
|
|
68280
|
+
});
|
|
68281
|
+
|
|
67653
68282
|
// src/user-attention-watchers.ts
|
|
67654
68283
|
function createUserAttentionWatchParentMonitor(options = {}) {
|
|
67655
68284
|
const parentPid = options.parentPid ?? process.ppid;
|
|
@@ -67688,7 +68317,7 @@ function isOriginalParentProcessAlive(options) {
|
|
|
67688
68317
|
}
|
|
67689
68318
|
function registerUserAttentionWatcher(options) {
|
|
67690
68319
|
return options.store.registerUserAttentionWatcher({
|
|
67691
|
-
id: options.id ?? (0,
|
|
68320
|
+
id: options.id ?? (0, import_node_crypto16.randomUUID)(),
|
|
67692
68321
|
provider: options.provider,
|
|
67693
68322
|
jobId: options.jobId,
|
|
67694
68323
|
nowMs: options.nowMs ?? Date.now(),
|
|
@@ -67767,11 +68396,11 @@ function userWatchEventDeliveredSentryExtra(event) {
|
|
|
67767
68396
|
hasDecision: String(event.hasDecision)
|
|
67768
68397
|
};
|
|
67769
68398
|
}
|
|
67770
|
-
var
|
|
68399
|
+
var import_node_crypto16, USER_ATTENTION_WATCH_REPLACED_MESSAGE, USER_ATTENTION_WATCHER_SCAN_MS, USER_ATTENTION_WATCHER_TTL_MS, USER_ATTENTION_WATCH_PARENT_CHECK_MS;
|
|
67771
68400
|
var init_user_attention_watchers = __esm({
|
|
67772
68401
|
"src/user-attention-watchers.ts"() {
|
|
67773
68402
|
"use strict";
|
|
67774
|
-
|
|
68403
|
+
import_node_crypto16 = require("node:crypto");
|
|
67775
68404
|
init_sentry_logger();
|
|
67776
68405
|
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.";
|
|
67777
68406
|
USER_ATTENTION_WATCHER_SCAN_MS = 500;
|
|
@@ -68029,7 +68658,6 @@ async function runListenerWithLock(options, paths) {
|
|
|
68029
68658
|
fetchSystemConfig: async () => fetchSystemConfig({
|
|
68030
68659
|
notifySessionExpired: (command) => service.tools.notifySessionExpired?.(command)
|
|
68031
68660
|
}),
|
|
68032
|
-
notifyAgentsWakeup: async (agentIds) => notifyAgentsWakeup(agentIds),
|
|
68033
68661
|
createSigner: (agent) => createOnchainosSigner(agent),
|
|
68034
68662
|
createInboundMiddleware: (deps) => createMiddlewareFromCoreDeps(store, deps, {
|
|
68035
68663
|
sessionStore,
|
|
@@ -68079,12 +68707,12 @@ async function runListenerWithLock(options, paths) {
|
|
|
68079
68707
|
});
|
|
68080
68708
|
}
|
|
68081
68709
|
});
|
|
68082
|
-
service.setPluginVersion("0.2.
|
|
68710
|
+
service.setPluginVersion("0.2.9-beta-912b775358-260824171011");
|
|
68083
68711
|
await service.init();
|
|
68084
68712
|
const pluginVersionStatus = service.pluginVersionStatus;
|
|
68085
68713
|
if (pluginVersionStatus.unavailable) {
|
|
68086
68714
|
throw new Error(
|
|
68087
|
-
`@okxweb3/a2a-node v${"0.2.
|
|
68715
|
+
`@okxweb3/a2a-node v${"0.2.9-beta-912b775358-260824171011"} is below the required minimum v${pluginVersionStatus.minVersion}`
|
|
68088
68716
|
);
|
|
68089
68717
|
}
|
|
68090
68718
|
const systemConfig = service.getSystemConfig();
|
|
@@ -68112,7 +68740,7 @@ async function runListenerWithLock(options, paths) {
|
|
|
68112
68740
|
onchainosAgentId: "*",
|
|
68113
68741
|
reason: "system-config missing sentryDsn",
|
|
68114
68742
|
pluginId: "@okxweb3/a2a-node",
|
|
68115
|
-
pluginVersion: "0.2.
|
|
68743
|
+
pluginVersion: "0.2.9-beta-912b775358-260824171011"
|
|
68116
68744
|
});
|
|
68117
68745
|
}
|
|
68118
68746
|
logWithTimestamp(
|
|
@@ -68355,6 +68983,7 @@ async function runListenerWithLock(options, paths) {
|
|
|
68355
68983
|
let intervalSec = Math.max(10, service.getSystemConfig().heartbeatInterval);
|
|
68356
68984
|
let offlineReplayIntervalSec = resolveOfflineReplayIntervalSec(service.getSystemConfig());
|
|
68357
68985
|
let xmtpClientRecycleIntervalSec = resolveXmtpClientRecycleIntervalSec(service.getSystemConfig());
|
|
68986
|
+
let wakeupDispatcher = null;
|
|
68358
68987
|
let timer;
|
|
68359
68988
|
let offlineReplayTimer;
|
|
68360
68989
|
let xmtpClientRecycleTimer;
|
|
@@ -68373,6 +69002,7 @@ async function runListenerWithLock(options, paths) {
|
|
|
68373
69002
|
versionRefresh: refreshOnchainosVersionMetadata,
|
|
68374
69003
|
refresh: syncTick
|
|
68375
69004
|
});
|
|
69005
|
+
void wakeupDispatcher?.dispatchNextChunk();
|
|
68376
69006
|
}, intervalSec * 1e3);
|
|
68377
69007
|
};
|
|
68378
69008
|
const scheduleOfflineReplayTimer = (nextIntervalSec) => {
|
|
@@ -68487,6 +69117,22 @@ async function runListenerWithLock(options, paths) {
|
|
|
68487
69117
|
});
|
|
68488
69118
|
await markDaemonReady(paths.daemonLockPath);
|
|
68489
69119
|
logWithTimestamp(`[okx-agent-task] daemon ready lock=${paths.daemonLockPath}`);
|
|
69120
|
+
void startWakeupNotifyPull({
|
|
69121
|
+
service,
|
|
69122
|
+
commands,
|
|
69123
|
+
sessionStore,
|
|
69124
|
+
// Stop enqueuing if a shutdown begins mid-delivery (fire-and-forget pull).
|
|
69125
|
+
shouldContinue: () => !stopping
|
|
69126
|
+
}).then((dispatcher) => {
|
|
69127
|
+
wakeupDispatcher = dispatcher;
|
|
69128
|
+
}).catch((err2) => {
|
|
69129
|
+
logger.error(LogEvent.WAKEUP_PULL_FAILED, err2 instanceof Error ? err2 : new Error(String(err2)), {
|
|
69130
|
+
component: "node_listener",
|
|
69131
|
+
stage: "wakeup_pull_start",
|
|
69132
|
+
reason: "wakeup_pull_unhandled_error"
|
|
69133
|
+
});
|
|
69134
|
+
logWithTimestamp("[okx-agent-task] WakeupNotify pull failed to start:", err2);
|
|
69135
|
+
});
|
|
68490
69136
|
await new Promise((resolve14) => {
|
|
68491
69137
|
const shutdown2 = (signal) => {
|
|
68492
69138
|
if (stopping) {
|
|
@@ -68499,6 +69145,7 @@ async function runListenerWithLock(options, paths) {
|
|
|
68499
69145
|
resolve14();
|
|
68500
69146
|
}, SHUTDOWN_FORCE_RESOLVE_MS);
|
|
68501
69147
|
void (async () => {
|
|
69148
|
+
logDroppedWakeupWorkOnShutdown(wakeupDispatcher);
|
|
68502
69149
|
deferredMaintenanceTasks.cancelAll();
|
|
68503
69150
|
if (timer) {
|
|
68504
69151
|
clearInterval(timer);
|
|
@@ -68560,6 +69207,7 @@ var init_listener = __esm({
|
|
|
68560
69207
|
init_file_store();
|
|
68561
69208
|
init_session_store();
|
|
68562
69209
|
init_command_processor();
|
|
69210
|
+
init_wakeup_pull();
|
|
68563
69211
|
init_command_store();
|
|
68564
69212
|
init_ai_dispatch_queue();
|
|
68565
69213
|
init_message_handler();
|
|
@@ -86823,7 +87471,7 @@ var require_fetch_pb = __commonJS({
|
|
|
86823
87471
|
}
|
|
86824
87472
|
});
|
|
86825
87473
|
}
|
|
86826
|
-
function
|
|
87474
|
+
function isPlainObject6(value) {
|
|
86827
87475
|
const isObject = Object.prototype.toString.call(value).slice(8, -1) === "Object";
|
|
86828
87476
|
const isObjLike = value !== null && isObject;
|
|
86829
87477
|
if (!isObjLike || !isObject) {
|
|
@@ -86846,7 +87494,7 @@ var require_fetch_pb = __commonJS({
|
|
|
86846
87494
|
const isNonEmptyPrimitiveArray = Array.isArray(value) && value.every((v) => isPrimitive(v)) && value.length > 0;
|
|
86847
87495
|
const isNonZeroValuePrimitive = isPrimitive(value) && !isZeroValuePrimitive(value);
|
|
86848
87496
|
let objectToMerge = {};
|
|
86849
|
-
if (
|
|
87497
|
+
if (isPlainObject6(value)) {
|
|
86850
87498
|
objectToMerge = flattenRequestPayload(value, newPath);
|
|
86851
87499
|
} else if (isNonZeroValuePrimitive || isNonEmptyPrimitiveArray) {
|
|
86852
87500
|
objectToMerge = { [newPath]: value };
|
|
@@ -112415,10 +113063,10 @@ var require_node4 = __commonJS({
|
|
|
112415
113063
|
|
|
112416
113064
|
// ../../node_modules/@xmtp/content-type-remote-attachment/dist/index.js
|
|
112417
113065
|
async function encrypt(plain, secret, additionalData) {
|
|
112418
|
-
const salt =
|
|
112419
|
-
const nonce =
|
|
113066
|
+
const salt = import_node_crypto17.webcrypto.getRandomValues(new Uint8Array(KDFSaltSize));
|
|
113067
|
+
const nonce = import_node_crypto17.webcrypto.getRandomValues(new Uint8Array(AESGCMNonceSize));
|
|
112420
113068
|
const key = await hkdf(secret, salt);
|
|
112421
|
-
const encrypted = await
|
|
113069
|
+
const encrypted = await import_node_crypto17.webcrypto.subtle.encrypt(aesGcmParams(nonce), key, plain);
|
|
112422
113070
|
return new Ciphertext({
|
|
112423
113071
|
aes256GcmHkdfSha256: {
|
|
112424
113072
|
payload: new Uint8Array(encrypted),
|
|
@@ -112432,7 +113080,7 @@ async function decrypt(encrypted, secret, additionalData) {
|
|
|
112432
113080
|
throw new Error("invalid payload ciphertext");
|
|
112433
113081
|
}
|
|
112434
113082
|
const key = await hkdf(secret, encrypted.aes256GcmHkdfSha256.hkdfSalt);
|
|
112435
|
-
const decrypted = await
|
|
113083
|
+
const decrypted = await import_node_crypto17.webcrypto.subtle.decrypt(aesGcmParams(encrypted.aes256GcmHkdfSha256.gcmNonce), key, encrypted.aes256GcmHkdfSha256.payload);
|
|
112436
113084
|
return new Uint8Array(decrypted);
|
|
112437
113085
|
}
|
|
112438
113086
|
function aesGcmParams(nonce, additionalData) {
|
|
@@ -112443,18 +113091,18 @@ function aesGcmParams(nonce, additionalData) {
|
|
|
112443
113091
|
return spec;
|
|
112444
113092
|
}
|
|
112445
113093
|
async function hkdf(secret, salt) {
|
|
112446
|
-
const key = await
|
|
113094
|
+
const key = await import_node_crypto17.webcrypto.subtle.importKey("raw", secret, "HKDF", false, [
|
|
112447
113095
|
"deriveKey"
|
|
112448
113096
|
]);
|
|
112449
|
-
return
|
|
113097
|
+
return import_node_crypto17.webcrypto.subtle.deriveKey({ name: "HKDF", hash: "SHA-256", salt, info: hkdfNoInfo }, key, { name: "AES-GCM", length: 256 }, false, ["encrypt", "decrypt"]);
|
|
112450
113098
|
}
|
|
112451
|
-
var import_proto,
|
|
113099
|
+
var import_proto, import_node_crypto17, ContentTypeAttachment, AttachmentCodec, KDFSaltSize, AESGCMNonceSize, AESGCMTagLength, Ciphertext, hkdfNoInfo, ContentTypeRemoteAttachment, RemoteAttachmentCodec;
|
|
112452
113100
|
var init_dist6 = __esm({
|
|
112453
113101
|
"../../node_modules/@xmtp/content-type-remote-attachment/dist/index.js"() {
|
|
112454
113102
|
init_dist5();
|
|
112455
113103
|
init_secp256k12();
|
|
112456
113104
|
import_proto = __toESM(require_node4(), 1);
|
|
112457
|
-
|
|
113105
|
+
import_node_crypto17 = require("node:crypto");
|
|
112458
113106
|
ContentTypeAttachment = new ContentTypeId({
|
|
112459
113107
|
authorityId: "xmtp.org",
|
|
112460
113108
|
typeId: "attachment",
|
|
@@ -112534,7 +113182,7 @@ var init_dist6 = __esm({
|
|
|
112534
113182
|
if (payload.length === 0) {
|
|
112535
113183
|
throw new Error(`no payload for remote attachment at ${remoteAttachment.url}`);
|
|
112536
113184
|
}
|
|
112537
|
-
const digestBytes = new Uint8Array(await
|
|
113185
|
+
const digestBytes = new Uint8Array(await import_node_crypto17.webcrypto.subtle.digest("SHA-256", payload));
|
|
112538
113186
|
const digest = etc.bytesToHex(digestBytes);
|
|
112539
113187
|
if (digest !== remoteAttachment.contentDigest) {
|
|
112540
113188
|
throw new Error("content digest does not match");
|
|
@@ -112558,7 +113206,7 @@ var init_dist6 = __esm({
|
|
|
112558
113206
|
return codec.decode(encodedContent, codecRegistry);
|
|
112559
113207
|
}
|
|
112560
113208
|
static async encodeEncrypted(content$1, codec) {
|
|
112561
|
-
const secret =
|
|
113209
|
+
const secret = import_node_crypto17.webcrypto.getRandomValues(new Uint8Array(32));
|
|
112562
113210
|
const encodedContent = import_proto.content.EncodedContent.encode(codec.encode(content$1, {
|
|
112563
113211
|
codecFor() {
|
|
112564
113212
|
return void 0;
|
|
@@ -112571,7 +113219,7 @@ var init_dist6 = __esm({
|
|
|
112571
113219
|
if (!salt || !nonce || !payload) {
|
|
112572
113220
|
throw new Error("missing encryption key");
|
|
112573
113221
|
}
|
|
112574
|
-
const digestBytes = new Uint8Array(await
|
|
113222
|
+
const digestBytes = new Uint8Array(await import_node_crypto17.webcrypto.subtle.digest("SHA-256", payload));
|
|
112575
113223
|
const digest = etc.bytesToHex(digestBytes);
|
|
112576
113224
|
return {
|
|
112577
113225
|
digest,
|
|
@@ -112789,7 +113437,7 @@ async function uploadFile(params) {
|
|
|
112789
113437
|
const attachment = { filename, mimeType, data: new Uint8Array(data) };
|
|
112790
113438
|
const encrypted = await RemoteAttachmentCodec.encodeEncrypted(attachment, new AttachmentCodec());
|
|
112791
113439
|
ensureFileDirs();
|
|
112792
|
-
const encryptedPath = (0, import_node_path33.resolve)(FILE_WORK_DIR, `${(0,
|
|
113440
|
+
const encryptedPath = (0, import_node_path33.resolve)(FILE_WORK_DIR, `${(0, import_node_crypto18.randomUUID)()}.enc`);
|
|
112793
113441
|
(0, import_node_fs27.writeFileSync)(encryptedPath, encrypted.payload);
|
|
112794
113442
|
try {
|
|
112795
113443
|
const stdout = runOnchainos([
|
|
@@ -112833,7 +113481,7 @@ async function uploadFile(params) {
|
|
|
112833
113481
|
}
|
|
112834
113482
|
async function downloadFile(params) {
|
|
112835
113483
|
ensureFileDirs();
|
|
112836
|
-
const encryptedPath = (0, import_node_path33.resolve)(FILE_WORK_DIR, `${(0,
|
|
113484
|
+
const encryptedPath = (0, import_node_path33.resolve)(FILE_WORK_DIR, `${(0, import_node_crypto18.randomUUID)()}.enc`);
|
|
112837
113485
|
try {
|
|
112838
113486
|
const stdout = runOnchainos([
|
|
112839
113487
|
"agent",
|
|
@@ -112858,7 +113506,7 @@ async function downloadFile(params) {
|
|
|
112858
113506
|
throw new Error(`file download failed: ${stdout}`);
|
|
112859
113507
|
}
|
|
112860
113508
|
const payload = new Uint8Array((0, import_node_fs27.readFileSync)(encryptedPath));
|
|
112861
|
-
const digestBytes = new Uint8Array(await
|
|
113509
|
+
const digestBytes = new Uint8Array(await import_node_crypto18.webcrypto.subtle.digest("SHA-256", payload));
|
|
112862
113510
|
const actualDigest = Array.from(digestBytes).map((byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
112863
113511
|
if (actualDigest !== params.digest) {
|
|
112864
113512
|
throw new Error(`file download digest verification failed: expected=${params.digest}, actual=${actualDigest}`);
|
|
@@ -112866,7 +113514,7 @@ async function downloadFile(params) {
|
|
|
112866
113514
|
const decryptedBytes = await decryptAttachmentPayload(payload, params);
|
|
112867
113515
|
const encodedContent = import_proto2.content.EncodedContent.decode(decryptedBytes);
|
|
112868
113516
|
const attachment = new AttachmentCodec().decode(encodedContent);
|
|
112869
|
-
const outputFilename = params.filename || attachment.filename || `${(0,
|
|
113517
|
+
const outputFilename = params.filename || attachment.filename || `${(0, import_node_crypto18.randomUUID)()}.bin`;
|
|
112870
113518
|
const outputDir = DOWNLOADS_DIR;
|
|
112871
113519
|
ensureA2aTaskDir(outputDir);
|
|
112872
113520
|
const outputPath = (0, import_node_path33.resolve)(outputDir, (0, import_node_path33.basename)(outputFilename));
|
|
@@ -112883,15 +113531,15 @@ async function decryptAttachmentPayload(payload, params) {
|
|
|
112883
113531
|
const secretBytes = new Uint8Array(Buffer.from(params.secret, "base64"));
|
|
112884
113532
|
const saltBytes = new Uint8Array(Buffer.from(params.salt, "base64"));
|
|
112885
113533
|
const nonceBytes = new Uint8Array(Buffer.from(params.nonce, "base64"));
|
|
112886
|
-
const hkdfKey = await
|
|
112887
|
-
const aesKey = await
|
|
113534
|
+
const hkdfKey = await import_node_crypto18.webcrypto.subtle.importKey("raw", secretBytes, "HKDF", false, ["deriveKey"]);
|
|
113535
|
+
const aesKey = await import_node_crypto18.webcrypto.subtle.deriveKey(
|
|
112888
113536
|
{ name: "HKDF", hash: "SHA-256", salt: saltBytes, info: new Uint8Array().buffer },
|
|
112889
113537
|
hkdfKey,
|
|
112890
113538
|
{ name: "AES-GCM", length: 256 },
|
|
112891
113539
|
false,
|
|
112892
113540
|
["decrypt"]
|
|
112893
113541
|
);
|
|
112894
|
-
return new Uint8Array(await
|
|
113542
|
+
return new Uint8Array(await import_node_crypto18.webcrypto.subtle.decrypt({ name: "AES-GCM", iv: nonceBytes }, aesKey, toArrayBuffer(payload)));
|
|
112895
113543
|
}
|
|
112896
113544
|
function toArrayBuffer(bytes) {
|
|
112897
113545
|
return bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength);
|
|
@@ -113031,12 +113679,12 @@ function readRequiredOption(args, name) {
|
|
|
113031
113679
|
}
|
|
113032
113680
|
return value;
|
|
113033
113681
|
}
|
|
113034
|
-
var
|
|
113682
|
+
var import_node_crypto18, import_node_fs27, import_node_path33, import_proto2, OKX_A2A_PATHS, OKX_A2A_HOME_DIR, FILE_WORK_DIR, DOWNLOADS_DIR, SYSTEM_CONFIG_PATH;
|
|
113035
113683
|
var init_file_cli = __esm({
|
|
113036
113684
|
"src/file-cli.ts"() {
|
|
113037
113685
|
"use strict";
|
|
113038
113686
|
init_win_spawn();
|
|
113039
|
-
|
|
113687
|
+
import_node_crypto18 = require("node:crypto");
|
|
113040
113688
|
import_node_fs27 = require("node:fs");
|
|
113041
113689
|
import_node_path33 = require("node:path");
|
|
113042
113690
|
init_dist6();
|
|
@@ -116519,7 +117167,7 @@ async function getCurrentNodeCliVersion() {
|
|
|
116519
117167
|
return await getGlobalNpmPackageVersion(UPDATE_PACKAGES.node) ?? getBundledNodeCliVersion();
|
|
116520
117168
|
}
|
|
116521
117169
|
function getBundledNodeCliVersion() {
|
|
116522
|
-
return true ? "0.2.
|
|
117170
|
+
return true ? "0.2.9-beta-912b775358-260824171011" : null;
|
|
116523
117171
|
}
|
|
116524
117172
|
function readConfiguredAiProvider() {
|
|
116525
117173
|
const explicit = process.env.OKX_A2A_AI_PROVIDER || process.env.OKX_AGENT_TASK_AI_CLI;
|
|
@@ -116729,7 +117377,7 @@ async function updateHermes(release, options) {
|
|
|
116729
117377
|
}
|
|
116730
117378
|
}
|
|
116731
117379
|
async function installGatewayPluginForDoctor(target) {
|
|
116732
|
-
const release = isPrereleaseVersion("0.2.
|
|
117380
|
+
const release = isPrereleaseVersion("0.2.9-beta-912b775358-260824171011") ? "beta" : "latest";
|
|
116733
117381
|
const insideTargetGateway = detectGatewayInvocation() === target;
|
|
116734
117382
|
const options = {
|
|
116735
117383
|
restart: !insideTargetGateway,
|
|
@@ -117782,7 +118430,7 @@ async function runDoctor(options = {}) {
|
|
|
117782
118430
|
platform: options.platform ?? process.platform,
|
|
117783
118431
|
env: options.env ?? process.env,
|
|
117784
118432
|
target: options.target ?? resolveDoctorTarget(options.env ?? process.env),
|
|
117785
|
-
cliVersion: options.cliVersion ?? (true ? "0.2.
|
|
118433
|
+
cliVersion: options.cliVersion ?? (true ? "0.2.9-beta-912b775358-260824171011" : "0.0.0"),
|
|
117786
118434
|
fixMode: options.fix === true,
|
|
117787
118435
|
nonInteractive: options.nonInteractive === true,
|
|
117788
118436
|
packageChanged: false,
|
|
@@ -118810,7 +119458,7 @@ init_sentry_config();
|
|
|
118810
119458
|
init_runtime_metadata();
|
|
118811
119459
|
var CURRENT_GATEWAY_SESSION_KEYS_ENV4 = "OKX_A2A_CURRENT_GATEWAY_SESSION_KEYS";
|
|
118812
119460
|
function printUsage3() {
|
|
118813
|
-
console.log(`okx-a2a ${"0.2.
|
|
119461
|
+
console.log(`okx-a2a ${"0.2.9-beta-912b775358-260824171011"}
|
|
118814
119462
|
|
|
118815
119463
|
Usage:
|
|
118816
119464
|
okx-a2a <command> [options]
|
|
@@ -118850,7 +119498,7 @@ Run \`okx-a2a <command> -h\` for command-specific help.
|
|
|
118850
119498
|
`);
|
|
118851
119499
|
}
|
|
118852
119500
|
function printVersion() {
|
|
118853
|
-
console.log("0.2.
|
|
119501
|
+
console.log("0.2.9-beta-912b775358-260824171011");
|
|
118854
119502
|
}
|
|
118855
119503
|
function printDaemonUsage() {
|
|
118856
119504
|
console.log(`Usage: okx-a2a daemon <start|restart|stop|status|autostart> [options]
|
|
@@ -120331,7 +120979,7 @@ async function main() {
|
|
|
120331
120979
|
if (command === "xmtp-test") {
|
|
120332
120980
|
const { handleXmtpTestCommand: handleXmtpTestCommand2 } = await Promise.resolve().then(() => (init_xmtp_test_cli(), xmtp_test_cli_exports));
|
|
120333
120981
|
await handleXmtpTestCommand2(process.argv.slice(3), {
|
|
120334
|
-
packageVersion: "0.2.
|
|
120982
|
+
packageVersion: "0.2.9-beta-912b775358-260824171011",
|
|
120335
120983
|
agentSdkVersion: "2.3.0",
|
|
120336
120984
|
nodeSdkVersion: "6.1.0",
|
|
120337
120985
|
nodeBindingsVersion: "1.11.0"
|