@okxweb3/a2a-node 0.1.5 → 0.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/dist/cli.js +349 -256
  2. package/dist/index.js +878 -765
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1697,6 +1697,520 @@ var init_session_store = __esm({
1697
1697
  }
1698
1698
  });
1699
1699
 
1700
+ // src/daemon-lock.ts
1701
+ function isProcessAlive(pid) {
1702
+ try {
1703
+ process.kill(pid, 0);
1704
+ return true;
1705
+ } catch (err2) {
1706
+ return err2.code === "EPERM";
1707
+ }
1708
+ }
1709
+ function ownerPath(lockPath) {
1710
+ return (0, import_node_path4.join)(lockPath, OWNER_FILE);
1711
+ }
1712
+ async function readDaemonLock(lockPath) {
1713
+ let metadata = null;
1714
+ try {
1715
+ const raw = await (0, import_promises.readFile)(ownerPath(lockPath), "utf8");
1716
+ metadata = JSON.parse(raw);
1717
+ } catch (err2) {
1718
+ const code2 = err2.code;
1719
+ if (code2 === "ENOENT") {
1720
+ try {
1721
+ const info = await (0, import_promises.stat)(lockPath);
1722
+ const stale = Date.now() - info.mtimeMs > EMPTY_LOCK_STALE_MS;
1723
+ return { metadata: null, running: !stale, stale, path: lockPath };
1724
+ } catch (statErr) {
1725
+ const statCode = statErr.code;
1726
+ if (statCode === "ENOENT") {
1727
+ return { metadata: null, running: false, stale: false, path: lockPath };
1728
+ }
1729
+ throw statErr;
1730
+ }
1731
+ }
1732
+ if (err2 instanceof SyntaxError) {
1733
+ return { metadata: null, running: false, stale: true, path: lockPath };
1734
+ }
1735
+ throw err2;
1736
+ }
1737
+ const running = Number.isInteger(metadata.pid) && metadata.pid > 0 && isProcessAlive(metadata.pid);
1738
+ return { metadata, running, stale: !running, path: lockPath };
1739
+ }
1740
+ async function markDaemonReady(lockPath) {
1741
+ const current = await readDaemonLock(lockPath);
1742
+ const metadata = current.metadata;
1743
+ if (!metadata || metadata.pid !== process.pid) {
1744
+ return;
1745
+ }
1746
+ await (0, import_promises.writeFile)(ownerPath(lockPath), `${JSON.stringify({
1747
+ ...metadata,
1748
+ ready: true,
1749
+ readyAt: (/* @__PURE__ */ new Date()).toISOString()
1750
+ }, null, 2)}
1751
+ `, "utf8");
1752
+ }
1753
+ async function removeLock(lockPath) {
1754
+ await (0, import_promises.rm)(lockPath, { recursive: true, force: true });
1755
+ }
1756
+ async function acquireDaemonLock(paths, entry) {
1757
+ const metadata = {
1758
+ pid: process.pid,
1759
+ startedAt: (/* @__PURE__ */ new Date()).toISOString(),
1760
+ cwd: process.cwd(),
1761
+ entry,
1762
+ homeDir: paths.homeDir,
1763
+ capabilities: DAEMON_CAPABILITIES,
1764
+ ready: false
1765
+ };
1766
+ ensureTaskDir(paths.runDir);
1767
+ for (let attempt = 0; attempt < 2; attempt += 1) {
1768
+ try {
1769
+ await (0, import_promises.mkdir)(paths.daemonLockPath, { mode: A2A_TASK_DIR_MODE });
1770
+ await chmodBestEffort(paths.daemonLockPath, A2A_TASK_DIR_MODE);
1771
+ await (0, import_promises.writeFile)(ownerPath(paths.daemonLockPath), `${JSON.stringify(metadata, null, 2)}
1772
+ `, "utf8");
1773
+ return {
1774
+ metadata,
1775
+ release: async () => {
1776
+ const current = await readDaemonLock(paths.daemonLockPath);
1777
+ if (current.metadata?.pid === process.pid) {
1778
+ await removeLock(paths.daemonLockPath);
1779
+ }
1780
+ }
1781
+ };
1782
+ } catch (err2) {
1783
+ const code2 = err2.code;
1784
+ if (code2 !== "EEXIST") {
1785
+ throw err2;
1786
+ }
1787
+ const current = await readDaemonLock(paths.daemonLockPath);
1788
+ if (current.running) {
1789
+ return null;
1790
+ }
1791
+ if (!current.stale) {
1792
+ return null;
1793
+ }
1794
+ await removeLock(paths.daemonLockPath);
1795
+ }
1796
+ }
1797
+ return null;
1798
+ }
1799
+ async function chmodBestEffort(path, mode) {
1800
+ try {
1801
+ await (0, import_promises.chmod)(path, mode);
1802
+ } catch (err2) {
1803
+ const code2 = err2.code;
1804
+ if (code2 !== "EPERM" && code2 !== "EACCES") {
1805
+ throw err2;
1806
+ }
1807
+ }
1808
+ }
1809
+ var import_promises, import_node_path4, OWNER_FILE, EMPTY_LOCK_STALE_MS, DAEMON_CAPABILITY_AI_DISPATCH, DAEMON_CAPABILITIES;
1810
+ var init_daemon_lock = __esm({
1811
+ "src/daemon-lock.ts"() {
1812
+ "use strict";
1813
+ import_promises = require("node:fs/promises");
1814
+ import_node_path4 = require("node:path");
1815
+ init_paths();
1816
+ init_a2a_paths();
1817
+ OWNER_FILE = "owner.json";
1818
+ EMPTY_LOCK_STALE_MS = 1e4;
1819
+ DAEMON_CAPABILITY_AI_DISPATCH = "ai-dispatch";
1820
+ DAEMON_CAPABILITIES = [
1821
+ DAEMON_CAPABILITY_AI_DISPATCH
1822
+ ];
1823
+ }
1824
+ });
1825
+
1826
+ // src/daemon.ts
1827
+ var daemon_exports = {};
1828
+ __export(daemon_exports, {
1829
+ ensureDaemonReady: () => ensureDaemonReady,
1830
+ getDaemonStatus: () => getDaemonStatus,
1831
+ startDaemon: () => startDaemon,
1832
+ stopDaemon: () => stopDaemon
1833
+ });
1834
+ async function readPid(pidPath) {
1835
+ try {
1836
+ const raw = await (0, import_promises2.readFile)(pidPath, "utf8");
1837
+ const pid = Number.parseInt(raw.trim(), 10);
1838
+ return Number.isInteger(pid) && pid > 0 ? pid : null;
1839
+ } catch (err2) {
1840
+ const code2 = err2.code;
1841
+ if (code2 === "ENOENT") {
1842
+ return null;
1843
+ }
1844
+ throw err2;
1845
+ }
1846
+ }
1847
+ async function removePid(pidPath) {
1848
+ try {
1849
+ await (0, import_promises2.unlink)(pidPath);
1850
+ } catch (err2) {
1851
+ const code2 = err2.code;
1852
+ if (code2 !== "ENOENT") {
1853
+ throw err2;
1854
+ }
1855
+ }
1856
+ }
1857
+ async function ensureDaemonDirs(homeDir) {
1858
+ const paths = resolveTaskPaths(homeDir);
1859
+ ensureTaskDir(paths.jobsDir);
1860
+ ensureTaskDir(paths.runDir);
1861
+ ensureTaskDir(paths.logsDir);
1862
+ ensureTaskDir(paths.commandsDir);
1863
+ ensureTaskDir(paths.downloadsDir);
1864
+ ensureTaskDir(paths.xmtpDir);
1865
+ ensureTaskDir(paths.sqliteDir);
1866
+ return paths;
1867
+ }
1868
+ async function ensureAiWorkspace(paths) {
1869
+ const aiWorkingDir = paths.workspaceDir;
1870
+ await (0, import_promises2.rm)(aiWorkingDir, { recursive: true, force: true });
1871
+ ensureTaskDir(aiWorkingDir);
1872
+ return aiWorkingDir;
1873
+ }
1874
+ async function waitForImmediateExit(child, timeoutMs) {
1875
+ return await new Promise((resolve6) => {
1876
+ let timer;
1877
+ const onExit = () => {
1878
+ clearTimeout(timer);
1879
+ resolve6(true);
1880
+ };
1881
+ timer = setTimeout(() => {
1882
+ child.off("exit", onExit);
1883
+ resolve6(false);
1884
+ }, timeoutMs);
1885
+ child.once("exit", onExit);
1886
+ });
1887
+ }
1888
+ async function getDaemonStatus(homeDir) {
1889
+ const paths = resolveTaskPaths(homeDir);
1890
+ const pid = await readPid(paths.pidPath);
1891
+ const lock = await readDaemonLock(paths.daemonLockPath);
1892
+ const lockPid = lock.metadata?.pid ?? null;
1893
+ const lockReadyStateKnown = !!lock.metadata && (typeof lock.metadata.ready === "boolean" || typeof lock.metadata.readyAt === "string");
1894
+ const lockReady = lockReadyStateKnown ? lock.metadata?.ready === true || typeof lock.metadata?.readyAt === "string" : true;
1895
+ if (lock.running) {
1896
+ return {
1897
+ running: true,
1898
+ pid: lockPid ?? pid,
1899
+ stale: false,
1900
+ capabilities: lock.metadata?.capabilities ?? [],
1901
+ ready: lockReady,
1902
+ readyAt: lock.metadata?.readyAt ?? null,
1903
+ readyStateKnown: lockReadyStateKnown,
1904
+ pidPath: paths.pidPath,
1905
+ lockPath: paths.daemonLockPath,
1906
+ lockPid,
1907
+ lockStale: false
1908
+ };
1909
+ }
1910
+ if (!pid) {
1911
+ return {
1912
+ running: false,
1913
+ pid: null,
1914
+ stale: lock.stale,
1915
+ capabilities: [],
1916
+ ready: false,
1917
+ readyAt: null,
1918
+ readyStateKnown: false,
1919
+ pidPath: paths.pidPath,
1920
+ lockPath: paths.daemonLockPath,
1921
+ lockPid,
1922
+ lockStale: lock.stale
1923
+ };
1924
+ }
1925
+ const running = isProcessAlive(pid);
1926
+ return {
1927
+ running,
1928
+ pid,
1929
+ stale: !running || lock.stale,
1930
+ capabilities: running ? lock.metadata?.capabilities ?? [] : [],
1931
+ ready: running && !lockReadyStateKnown ? true : running && lockReady,
1932
+ readyAt: running ? lock.metadata?.readyAt ?? null : null,
1933
+ readyStateKnown: running && lockReadyStateKnown,
1934
+ pidPath: paths.pidPath,
1935
+ lockPath: paths.daemonLockPath,
1936
+ lockPid,
1937
+ lockStale: lock.stale
1938
+ };
1939
+ }
1940
+ async function startDaemon(homeDir) {
1941
+ const paths = await ensureDaemonDirs(homeDir);
1942
+ const aiWorkingDir = await ensureAiWorkspace(paths);
1943
+ const current = await getDaemonStatus(homeDir);
1944
+ if (current.running) {
1945
+ return {
1946
+ ...current,
1947
+ started: false,
1948
+ logPath: paths.listenerLogPath
1949
+ };
1950
+ }
1951
+ if (current.stale) {
1952
+ await removePid(paths.pidPath);
1953
+ }
1954
+ const store = new SessionStore({ homeDir });
1955
+ try {
1956
+ store.setSetting("ai_working_dir", aiWorkingDir);
1957
+ store.resetGlobalSession(SYSTEM_NOTIFICATION_SESSION_KEY);
1958
+ } finally {
1959
+ store.close();
1960
+ }
1961
+ const logFd = (0, import_node_fs3.openSync)(paths.listenerLogPath, "a");
1962
+ const entry = process.env.OKX_AGENT_TASK_CLI_PATH || (0, import_node_path5.join)(__dirname, "cli.js");
1963
+ const daemonCwd = (0, import_node_path5.join)(__dirname, "..");
1964
+ const child = (0, import_node_child_process.spawn)(process.execPath, [entry, "run"], {
1965
+ cwd: daemonCwd,
1966
+ detached: true,
1967
+ // win32: keep the detached daemon from flashing/holding a console window.
1968
+ // Ignored on every non-win32 platform.
1969
+ windowsHide: true,
1970
+ env: {
1971
+ ...process.env,
1972
+ OKX_AGENT_TASK_HOME: paths.homeDir,
1973
+ OKX_AGENT_TASK_DAEMON: "1",
1974
+ OKX_A2A_AI_CWD: aiWorkingDir,
1975
+ OKX_AGENT_TASK_AI_CWD: aiWorkingDir
1976
+ },
1977
+ stdio: ["ignore", logFd, logFd]
1978
+ });
1979
+ (0, import_node_fs3.closeSync)(logFd);
1980
+ child.unref();
1981
+ await (0, import_promises2.writeFile)(paths.pidPath, `${child.pid ?? ""}
1982
+ `, "utf8");
1983
+ if (await waitForImmediateExit(child, START_EXIT_CHECK_MS)) {
1984
+ const status = await getDaemonStatus(homeDir);
1985
+ if (status.running && status.lockPid) {
1986
+ await (0, import_promises2.writeFile)(paths.pidPath, `${status.lockPid}
1987
+ `, "utf8");
1988
+ } else {
1989
+ await removePid(paths.pidPath);
1990
+ }
1991
+ return {
1992
+ ...status,
1993
+ started: false,
1994
+ logPath: paths.listenerLogPath
1995
+ };
1996
+ }
1997
+ return {
1998
+ running: true,
1999
+ pid: child.pid ?? null,
2000
+ stale: false,
2001
+ capabilities: DAEMON_CAPABILITIES,
2002
+ ready: false,
2003
+ readyAt: null,
2004
+ readyStateKnown: true,
2005
+ pidPath: paths.pidPath,
2006
+ lockPath: paths.daemonLockPath,
2007
+ lockPid: child.pid ?? null,
2008
+ lockStale: false,
2009
+ started: true,
2010
+ logPath: paths.listenerLogPath
2011
+ };
2012
+ }
2013
+ async function waitForExit(pid, timeoutMs) {
2014
+ const deadline = Date.now() + timeoutMs;
2015
+ while (Date.now() < deadline) {
2016
+ if (!isProcessAlive(pid)) {
2017
+ return true;
2018
+ }
2019
+ await new Promise((resolve6) => setTimeout(resolve6, 100));
2020
+ }
2021
+ return !isProcessAlive(pid);
2022
+ }
2023
+ function signalProcess(pid, signal) {
2024
+ try {
2025
+ process.kill(pid, signal);
2026
+ return true;
2027
+ } catch (err2) {
2028
+ const code2 = err2.code;
2029
+ if (code2 === "ESRCH") {
2030
+ return false;
2031
+ }
2032
+ throw err2;
2033
+ }
2034
+ }
2035
+ async function stopDaemon(homeDir) {
2036
+ const paths = resolveTaskPaths(homeDir);
2037
+ const current = await getDaemonStatus(homeDir);
2038
+ if (!current.pid) {
2039
+ return { ...current, stopped: false };
2040
+ }
2041
+ if (!current.running) {
2042
+ await removePid(paths.pidPath);
2043
+ return {
2044
+ running: false,
2045
+ pid: current.pid,
2046
+ stale: false,
2047
+ capabilities: [],
2048
+ ready: false,
2049
+ readyAt: null,
2050
+ readyStateKnown: false,
2051
+ pidPath: paths.pidPath,
2052
+ lockPath: paths.daemonLockPath,
2053
+ lockPid: current.lockPid,
2054
+ lockStale: current.lockStale,
2055
+ stopped: false
2056
+ };
2057
+ }
2058
+ const signalled = signalProcess(current.pid, "SIGTERM");
2059
+ let forced = false;
2060
+ let exited = !signalled || await waitForExit(current.pid, STOP_GRACE_MS);
2061
+ if (!exited) {
2062
+ forced = true;
2063
+ const killed = signalProcess(current.pid, "SIGKILL");
2064
+ exited = !killed || await waitForExit(current.pid, FORCE_KILL_GRACE_MS);
2065
+ }
2066
+ if (exited) {
2067
+ await removePid(paths.pidPath);
2068
+ }
2069
+ return {
2070
+ running: !exited,
2071
+ pid: current.pid,
2072
+ stale: false,
2073
+ capabilities: exited ? [] : current.capabilities,
2074
+ ready: !exited && current.ready,
2075
+ readyAt: !exited ? current.readyAt : null,
2076
+ readyStateKnown: !exited && current.readyStateKnown,
2077
+ pidPath: paths.pidPath,
2078
+ lockPath: paths.daemonLockPath,
2079
+ lockPid: current.lockPid,
2080
+ lockStale: current.lockStale,
2081
+ stopped: exited,
2082
+ forced
2083
+ };
2084
+ }
2085
+ async function ensureDaemonReady(options = {}) {
2086
+ const paths = resolveTaskPaths(options.homeDir);
2087
+ const commandName = options.commandName ?? "command";
2088
+ const timeoutMs = options.timeoutMs ?? readReadyTimeoutMs(options.env ?? process.env);
2089
+ let status = await getDaemonStatus(options.homeDir);
2090
+ let started = false;
2091
+ let logPath = paths.listenerLogPath;
2092
+ if (!status.running) {
2093
+ options.stderr?.write(`[okx-a2a] ${commandName} requires the daemon; starting daemon...
2094
+ `);
2095
+ const startResult = await startDaemon(options.homeDir);
2096
+ started = startResult.started;
2097
+ logPath = startResult.logPath;
2098
+ status = startResult;
2099
+ if (!status.running) {
2100
+ throw new Error(
2101
+ `${commandName} requires the daemon, but automatic daemon start failed. Check ${logPath} or run \`okx-a2a daemon restart\`.`
2102
+ );
2103
+ }
2104
+ status = await waitForDaemonReady({
2105
+ homeDir: options.homeDir,
2106
+ timeoutMs,
2107
+ requiredCapabilities: options.requiredCapabilities,
2108
+ requireKnownReadyState: true,
2109
+ logPath,
2110
+ commandName
2111
+ });
2112
+ options.stderr?.write(`[okx-a2a] daemon ready pid=${status.pid ?? "(unknown)"} log=${logPath}
2113
+ `);
2114
+ } else if (status.readyStateKnown && !status.ready) {
2115
+ status = await waitForDaemonReady({
2116
+ homeDir: options.homeDir,
2117
+ timeoutMs,
2118
+ requiredCapabilities: options.requiredCapabilities,
2119
+ requireKnownReadyState: false,
2120
+ logPath,
2121
+ commandName
2122
+ });
2123
+ }
2124
+ assertRequiredCapabilities(status, options.requiredCapabilities, commandName);
2125
+ return {
2126
+ ...status,
2127
+ started,
2128
+ logPath
2129
+ };
2130
+ }
2131
+ async function waitForDaemonReady(options) {
2132
+ const deadline = Date.now() + Math.max(0, options.timeoutMs);
2133
+ let lastStatus = await getDaemonStatus(options.homeDir);
2134
+ while (Date.now() <= deadline) {
2135
+ const status = await getDaemonStatus(options.homeDir);
2136
+ lastStatus = status;
2137
+ if (!status.running) {
2138
+ if (status.stale) {
2139
+ throw new Error(
2140
+ `${options.commandName} requires the daemon, but the daemon exited before becoming ready. Check ${options.logPath} or run \`okx-a2a daemon restart\`.`
2141
+ );
2142
+ }
2143
+ } else if (isReadyForCommand(status, options.requiredCapabilities, options.requireKnownReadyState)) {
2144
+ return status;
2145
+ } else if (status.ready && findMissingCapabilities(status, options.requiredCapabilities).length > 0) {
2146
+ assertRequiredCapabilities(status, options.requiredCapabilities, options.commandName);
2147
+ }
2148
+ await sleep(Math.min(READY_POLL_MS, Math.max(1, deadline - Date.now() + 1)));
2149
+ }
2150
+ const missing = findMissingCapabilities(lastStatus, options.requiredCapabilities);
2151
+ const capabilitySuffix = missing.length > 0 ? ` missingCapabilities=${missing.join(",")}` : "";
2152
+ throw new Error(
2153
+ `${options.commandName} requires the daemon, but it did not become ready within ${options.timeoutMs}ms${capabilitySuffix}. Check ${options.logPath} or run \`okx-a2a daemon restart\`.`
2154
+ );
2155
+ }
2156
+ function isReadyForCommand(status, requiredCapabilities, requireKnownReadyState = false) {
2157
+ if (!status.running) {
2158
+ return false;
2159
+ }
2160
+ if (requireKnownReadyState && !status.readyStateKnown) {
2161
+ return false;
2162
+ }
2163
+ if (status.readyStateKnown && !status.ready) {
2164
+ return false;
2165
+ }
2166
+ return findMissingCapabilities(status, requiredCapabilities).length === 0;
2167
+ }
2168
+ function assertRequiredCapabilities(status, requiredCapabilities, commandName) {
2169
+ const missing = findMissingCapabilities(status, requiredCapabilities);
2170
+ if (missing.length === 0) {
2171
+ return;
2172
+ }
2173
+ throw new Error(
2174
+ `${commandName} requires a daemon with ${missing.join(",")} support. Run \`okx-a2a daemon restart\` first.`
2175
+ );
2176
+ }
2177
+ function findMissingCapabilities(status, requiredCapabilities) {
2178
+ if (!requiredCapabilities || requiredCapabilities.length === 0) {
2179
+ return [];
2180
+ }
2181
+ return requiredCapabilities.filter((capability) => !status.capabilities.includes(capability));
2182
+ }
2183
+ function readReadyTimeoutMs(env) {
2184
+ const raw = env[DAEMON_READY_TIMEOUT_ENV]?.trim();
2185
+ if (!raw) {
2186
+ return DEFAULT_READY_TIMEOUT_MS;
2187
+ }
2188
+ const parsed = Number(raw);
2189
+ return Number.isFinite(parsed) && parsed > 0 ? parsed : DEFAULT_READY_TIMEOUT_MS;
2190
+ }
2191
+ function sleep(ms) {
2192
+ return new Promise((resolve6) => setTimeout(resolve6, ms));
2193
+ }
2194
+ var import_node_fs3, import_promises2, import_node_child_process, import_node_path5, STOP_GRACE_MS, FORCE_KILL_GRACE_MS, START_EXIT_CHECK_MS, DEFAULT_READY_TIMEOUT_MS, READY_POLL_MS, DAEMON_READY_TIMEOUT_ENV;
2195
+ var init_daemon = __esm({
2196
+ "src/daemon.ts"() {
2197
+ "use strict";
2198
+ import_node_fs3 = require("node:fs");
2199
+ import_promises2 = require("node:fs/promises");
2200
+ import_node_child_process = require("node:child_process");
2201
+ import_node_path5 = require("node:path");
2202
+ init_paths();
2203
+ init_session_store();
2204
+ init_daemon_lock();
2205
+ STOP_GRACE_MS = 5e3;
2206
+ FORCE_KILL_GRACE_MS = 5e3;
2207
+ START_EXIT_CHECK_MS = 750;
2208
+ DEFAULT_READY_TIMEOUT_MS = 12e4;
2209
+ READY_POLL_MS = 250;
2210
+ DAEMON_READY_TIMEOUT_ENV = "OKX_A2A_DAEMON_READY_TIMEOUT_MS";
2211
+ }
2212
+ });
2213
+
1700
2214
  // ../core/src/log.ts
1701
2215
  function formatLogTimestamp(date = /* @__PURE__ */ new Date()) {
1702
2216
  return date.toLocaleString(void 0, {
@@ -70908,6 +71422,207 @@ var require_ws = __commonJS({
70908
71422
  }
70909
71423
  });
70910
71424
 
71425
+ // src/win-native-launcher.ts
71426
+ var win_native_launcher_exports = {};
71427
+ __export(win_native_launcher_exports, {
71428
+ NATIVE_LAUNCHER_EXE_NAME: () => NATIVE_LAUNCHER_EXE_NAME,
71429
+ buildLauncherEntryJs: () => buildLauncherEntryJs,
71430
+ buildSeaConfig: () => buildSeaConfig,
71431
+ ensureWindowsNativeLauncher: () => ensureWindowsNativeLauncher,
71432
+ findWindowsNativeOkxA2aExe: () => findWindowsNativeOkxA2aExe,
71433
+ installWindowsNativeLauncher: () => installWindowsNativeLauncher,
71434
+ resolveRunningCliPath: () => resolveRunningCliPath
71435
+ });
71436
+ function isPostjectRunnable() {
71437
+ try {
71438
+ const probe = spawnSyncCompat(POSTJECT_BIN, ["--help"], {
71439
+ stdio: "ignore",
71440
+ windowsHide: true,
71441
+ timeout: 3e4
71442
+ });
71443
+ return probe.status === 0;
71444
+ } catch {
71445
+ return false;
71446
+ }
71447
+ }
71448
+ function resolvePostjectCommand() {
71449
+ try {
71450
+ const cliPath = (0, import_node_module.createRequire)(__filename).resolve("postject/dist/cli.js");
71451
+ if ((0, import_node_fs16.existsSync)(cliPath)) {
71452
+ return { command: process.execPath, prefixArgs: [cliPath] };
71453
+ }
71454
+ } catch {
71455
+ }
71456
+ if (!isPostjectRunnable()) {
71457
+ logWinCompat(`${WIN_COMPAT_LOG_PREFIX} native launcher: installing ${POSTJECT_SPEC} globally`);
71458
+ const install = spawnSyncCompat("npm", [
71459
+ "install",
71460
+ "-g",
71461
+ POSTJECT_SPEC,
71462
+ "--no-audit",
71463
+ "--no-fund",
71464
+ "--loglevel=error"
71465
+ ], { encoding: "utf8", windowsHide: true, timeout: 18e4 });
71466
+ if (install.status !== 0 || !isPostjectRunnable()) {
71467
+ throw new Error(
71468
+ `failed to install ${POSTJECT_SPEC} (needed to build okx-a2a.exe): ${String(install.stderr || install.error?.message || "unknown error").slice(0, 300)}`
71469
+ );
71470
+ }
71471
+ }
71472
+ return { command: POSTJECT_BIN, prefixArgs: [] };
71473
+ }
71474
+ function injectSeaBlob(exePath, blobPath, isMac) {
71475
+ const { command, prefixArgs: prefixArgs2 } = resolvePostjectCommand();
71476
+ const args = [
71477
+ ...prefixArgs2,
71478
+ exePath,
71479
+ "NODE_SEA_BLOB",
71480
+ blobPath,
71481
+ "--sentinel-fuse",
71482
+ SEA_SENTINEL_FUSE,
71483
+ "--overwrite"
71484
+ ];
71485
+ if (isMac) {
71486
+ args.push("--macho-segment-name", "NODE_SEA");
71487
+ }
71488
+ const result = spawnSyncCompat(command, args, {
71489
+ encoding: "utf8",
71490
+ windowsHide: true,
71491
+ timeout: 12e4
71492
+ });
71493
+ if (result.status !== 0) {
71494
+ throw new Error(
71495
+ `postject injection failed: ${String(result.stderr || result.error?.message || `exit ${result.status}`).slice(0, 300)}`
71496
+ );
71497
+ }
71498
+ }
71499
+ function buildLauncherEntryJs(cliPath) {
71500
+ const target = JSON.stringify(cliPath);
71501
+ return [
71502
+ 'const { createRequire } = require("node:module");',
71503
+ `const nodeRequire = createRequire(${target});`,
71504
+ `nodeRequire(${target});`,
71505
+ ""
71506
+ ].join("\n");
71507
+ }
71508
+ function buildSeaConfig(entryPath, blobPath) {
71509
+ return `${JSON.stringify(
71510
+ {
71511
+ main: entryPath,
71512
+ output: blobPath,
71513
+ disableExperimentalSEAWarning: true
71514
+ },
71515
+ null,
71516
+ 2
71517
+ )}
71518
+ `;
71519
+ }
71520
+ async function installWindowsNativeLauncher(options) {
71521
+ const nodeExe = options.nodeExe ?? process.execPath;
71522
+ if (!(0, import_node_fs16.existsSync)(options.cliPath)) {
71523
+ throw new Error(`cannot build okx-a2a.exe: CLI entry not found at ${options.cliPath}`);
71524
+ }
71525
+ if (!(0, import_node_fs16.existsSync)(nodeExe)) {
71526
+ throw new Error(`cannot build okx-a2a.exe: node executable not found at ${nodeExe}`);
71527
+ }
71528
+ const exePath = (0, import_node_path22.join)(options.targetDir, NATIVE_LAUNCHER_EXE_NAME);
71529
+ (0, import_node_fs16.mkdirSync)(options.targetDir, { recursive: true });
71530
+ const work = (0, import_node_fs16.mkdtempSync)((0, import_node_path22.join)((0, import_node_os7.tmpdir)(), "okx-a2a-sea-"));
71531
+ try {
71532
+ const entryPath = (0, import_node_path22.join)(work, "launcher-entry.js");
71533
+ const blobPath = (0, import_node_path22.join)(work, "okx-a2a.blob");
71534
+ const configPath = (0, import_node_path22.join)(work, "sea-config.json");
71535
+ (0, import_node_fs16.writeFileSync)(entryPath, buildLauncherEntryJs(options.cliPath), "utf8");
71536
+ (0, import_node_fs16.writeFileSync)(configPath, buildSeaConfig(entryPath, blobPath), "utf8");
71537
+ (0, import_node_child_process5.execFileSync)(nodeExe, ["--experimental-sea-config", configPath], {
71538
+ stdio: "ignore",
71539
+ windowsHide: true
71540
+ });
71541
+ (0, import_node_fs16.copyFileSync)(nodeExe, exePath);
71542
+ const isMac = process.platform === "darwin";
71543
+ if (isMac) {
71544
+ try {
71545
+ (0, import_node_child_process5.execFileSync)("codesign", ["--remove-signature", exePath], { stdio: "ignore" });
71546
+ } catch {
71547
+ }
71548
+ }
71549
+ injectSeaBlob(exePath, blobPath, isMac);
71550
+ if (isMac) {
71551
+ try {
71552
+ (0, import_node_child_process5.execFileSync)("codesign", ["--sign", "-", exePath], { stdio: "ignore" });
71553
+ } catch {
71554
+ }
71555
+ }
71556
+ logWinCompat(
71557
+ `${WIN_COMPAT_LOG_PREFIX} native launcher: built ${exePath} from node=${nodeExe} cli=${options.cliPath}`
71558
+ );
71559
+ return { exePath, cliPath: options.cliPath, nodeExe };
71560
+ } finally {
71561
+ (0, import_node_fs16.rmSync)(work, { recursive: true, force: true });
71562
+ }
71563
+ }
71564
+ function findWindowsNativeOkxA2aExe(pathValue, appData, userProfile, fileExists2 = import_node_fs16.existsSync) {
71565
+ const dirs = pathValue.split(";").map((d) => d.trim()).filter(Boolean);
71566
+ if (appData) {
71567
+ dirs.push((0, import_node_path22.join)(appData, "npm"));
71568
+ }
71569
+ if (userProfile) {
71570
+ dirs.push((0, import_node_path22.join)(userProfile, ".local", "bin"));
71571
+ }
71572
+ for (const dir of dirs) {
71573
+ const candidate = (0, import_node_path22.join)(dir, NATIVE_LAUNCHER_EXE_NAME);
71574
+ if (fileExists2(candidate)) {
71575
+ return candidate;
71576
+ }
71577
+ }
71578
+ return null;
71579
+ }
71580
+ function resolveRunningCliPath() {
71581
+ const fromArgv = process.argv[1];
71582
+ if (fromArgv && /(?:^|[\\/])cli\.js$/.test(fromArgv) && (0, import_node_fs16.existsSync)(fromArgv)) {
71583
+ return fromArgv;
71584
+ }
71585
+ const beside = (0, import_node_path22.join)(__dirname, "cli.js");
71586
+ if ((0, import_node_fs16.existsSync)(beside)) {
71587
+ return beside;
71588
+ }
71589
+ if (fromArgv) {
71590
+ return fromArgv;
71591
+ }
71592
+ throw new Error("could not resolve the running okx-a2a CLI path for the native launcher");
71593
+ }
71594
+ async function ensureWindowsNativeLauncher(options = {}) {
71595
+ const platform = options.platform ?? process.platform;
71596
+ if (platform !== "win32") {
71597
+ return null;
71598
+ }
71599
+ const env = options.env ?? process.env;
71600
+ const existing = findWindowsNativeOkxA2aExe(env.PATH ?? env.Path ?? "", env.APPDATA, env.USERPROFILE);
71601
+ if (existing) {
71602
+ return { exePath: existing, installed: false };
71603
+ }
71604
+ const targetDir = env.APPDATA ? (0, import_node_path22.join)(env.APPDATA, "npm") : (0, import_node_path22.join)(env.USERPROFILE ?? (0, import_node_os7.homedir)(), ".local", "bin");
71605
+ const result = await installWindowsNativeLauncher({ cliPath: resolveRunningCliPath(), targetDir });
71606
+ return { exePath: result.exePath, installed: true };
71607
+ }
71608
+ var import_node_child_process5, import_node_fs16, import_node_module, import_node_os7, import_node_path22, SEA_SENTINEL_FUSE, NATIVE_LAUNCHER_EXE_NAME, POSTJECT_SPEC, POSTJECT_BIN;
71609
+ var init_win_native_launcher = __esm({
71610
+ "src/win-native-launcher.ts"() {
71611
+ "use strict";
71612
+ import_node_child_process5 = require("node:child_process");
71613
+ import_node_fs16 = require("node:fs");
71614
+ import_node_module = require("node:module");
71615
+ import_node_os7 = require("node:os");
71616
+ import_node_path22 = require("node:path");
71617
+ init_win_compat();
71618
+ init_win_spawn();
71619
+ SEA_SENTINEL_FUSE = "NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2";
71620
+ NATIVE_LAUNCHER_EXE_NAME = "okx-a2a.exe";
71621
+ POSTJECT_SPEC = "postject@1.0.0-alpha.6";
71622
+ POSTJECT_BIN = "postject";
71623
+ }
71624
+ });
71625
+
70911
71626
  // src/update-cli.ts
70912
71627
  var update_cli_exports = {};
70913
71628
  __export(update_cli_exports, {
@@ -70933,6 +71648,8 @@ __export(update_cli_exports, {
70933
71648
  parseUpdateArgs: () => parseUpdateArgs,
70934
71649
  printSetupUsage: () => printSetupUsage,
70935
71650
  printUpdateUsage: () => printUpdateUsage,
71651
+ resolveHermesConfigPath: () => resolveHermesConfigPath,
71652
+ resolveHermesPluginYamlPath: () => resolveHermesPluginYamlPath,
70936
71653
  runProviderLoginInteractive: () => runProviderLoginInteractive,
70937
71654
  setRedirectCommandStdoutToStderr: () => setRedirectCommandStdoutToStderr
70938
71655
  });
@@ -71146,6 +71863,7 @@ async function runSetup(options) {
71146
71863
  if (nodeChange.nodeChanged && provider) {
71147
71864
  await restartNodeDaemonAfterNodeSetup();
71148
71865
  }
71866
+ await ensureWindowsNativeLauncherForSetup();
71149
71867
  return {
71150
71868
  ok: true,
71151
71869
  state: "ready",
@@ -71179,6 +71897,7 @@ async function runSetup(options) {
71179
71897
  if (changes.pluginChanged) {
71180
71898
  await restartGatewayAfterSetup(resolvedTarget);
71181
71899
  }
71900
+ await ensureWindowsNativeLauncherForSetup();
71182
71901
  warnIfProviderMismatch(resolvedTarget);
71183
71902
  return {
71184
71903
  ok: true,
@@ -71625,7 +72344,7 @@ async function getCurrentNodeCliVersion() {
71625
72344
  return await getGlobalNpmPackageVersion(UPDATE_PACKAGES.node) ?? getBundledNodeCliVersion();
71626
72345
  }
71627
72346
  function getBundledNodeCliVersion() {
71628
- return true ? "0.1.5" : null;
72347
+ return true ? "0.1.6" : null;
71629
72348
  }
71630
72349
  function readConfiguredAiProvider() {
71631
72350
  const explicit = process.env.OKX_A2A_AI_PROVIDER || process.env.OKX_AGENT_TASK_AI_CLI;
@@ -71656,10 +72375,29 @@ async function restartNodeDaemonAfterUpdate() {
71656
72375
  }
71657
72376
  async function installNode(release, label) {
71658
72377
  const spec = buildNpmPackageSpec("node", release);
72378
+ if (process.platform === "win32") {
72379
+ const { getDaemonStatus: getDaemonStatus2, stopDaemon: stopDaemon2 } = await Promise.resolve().then(() => (init_daemon(), daemon_exports));
72380
+ const status = await getDaemonStatus2();
72381
+ if (status.running) {
72382
+ console.log(`[${label}] stopping the running daemon before reinstalling on Windows (its native addons lock the package dir)`);
72383
+ await stopDaemon2();
72384
+ }
72385
+ }
71659
72386
  console.log(`[${label}] installing ${spec}`);
71660
72387
  await runCommand("npm", ["install", "-g", spec]);
71661
72388
  console.log(`[${label}] okx-a2a node CLI ${label === "setup" ? "setup" : "update"} done`);
71662
72389
  }
72390
+ async function ensureWindowsNativeLauncherForSetup() {
72391
+ if (process.platform !== "win32") {
72392
+ return;
72393
+ }
72394
+ const { ensureWindowsNativeLauncher: ensureWindowsNativeLauncher2 } = await Promise.resolve().then(() => (init_win_native_launcher(), win_native_launcher_exports));
72395
+ const result = await ensureWindowsNativeLauncher2();
72396
+ if (!result) {
72397
+ return;
72398
+ }
72399
+ console.log(result.installed ? `[setup] built native okx-a2a.exe launcher at ${result.exePath}` : `[setup] native okx-a2a.exe launcher already present at ${result.exePath}`);
72400
+ }
71663
72401
  async function restartNodeDaemonAfterSetup(provider) {
71664
72402
  console.log(`[setup] restarting okx-a2a daemon after node CLI setup with provider=${provider}`);
71665
72403
  await runCommand("okx-a2a", ["daemon", "restart", "--provider", provider]);
@@ -71791,17 +72529,17 @@ async function updateHermes(release, options) {
71791
72529
  assertNotRunningInsideGateway("hermes");
71792
72530
  }
71793
72531
  const spec = buildNpmPackageSpec("hermes", release);
71794
- const workDir = await (0, import_promises7.mkdtemp)((0, import_node_path22.join)((0, import_node_os7.tmpdir)(), `okx-a2a-${label}-hermes-`));
72532
+ const workDir = await (0, import_promises7.mkdtemp)((0, import_node_path23.join)((0, import_node_os8.tmpdir)(), `okx-a2a-${label}-hermes-`));
71795
72533
  try {
71796
72534
  console.log(`[${label}] downloading ${spec}`);
71797
72535
  const npmTarball = await npmPack(spec, workDir);
71798
- const npmPackageDir = (0, import_node_path22.join)(workDir, "npm-package");
72536
+ const npmPackageDir = (0, import_node_path23.join)(workDir, "npm-package");
71799
72537
  await runCommand("tar", ["-xzf", npmTarball, "-C", npmPackageDir], { ensureDir: npmPackageDir });
71800
- const pluginTarball = await findHermesPluginTarball((0, import_node_path22.join)(npmPackageDir, "package", "dist"));
71801
- const pluginDir = (0, import_node_path22.join)(workDir, "plugin");
72538
+ const pluginTarball = await findHermesPluginTarball((0, import_node_path23.join)(npmPackageDir, "package", "dist"));
72539
+ const pluginDir = (0, import_node_path23.join)(workDir, "plugin");
71802
72540
  await runCommand("tar", ["-xzf", pluginTarball, "-C", pluginDir], { ensureDir: pluginDir });
71803
72541
  const unpackedPluginDir = await findFirstDirectory(pluginDir);
71804
- const installer = (0, import_node_path22.join)(unpackedPluginDir, "scripts", "install-or-upgrade.sh");
72542
+ const installer = (0, import_node_path23.join)(unpackedPluginDir, "scripts", "install-or-upgrade.sh");
71805
72543
  console.log(`[${label}] running ${installer}`);
71806
72544
  await runCommand("bash", [installer, ...options.restart ? ["--restart"] : []], { cwd: unpackedPluginDir });
71807
72545
  await normalizeHermesOkxA2aPluginConfig();
@@ -71816,7 +72554,7 @@ async function updateHermes(release, options) {
71816
72554
  }
71817
72555
  }
71818
72556
  async function installGatewayPluginForDoctor(target) {
71819
- const release = isPrereleaseVersion("0.1.5") ? "beta" : "latest";
72557
+ const release = isPrereleaseVersion("0.1.6") ? "beta" : "latest";
71820
72558
  const insideTargetGateway = detectGatewayInvocation() === target;
71821
72559
  const options = {
71822
72560
  restart: !insideTargetGateway,
@@ -71867,7 +72605,7 @@ async function ensureHermesOkxA2aPluginConfig(configFile = resolveHermesConfigPa
71867
72605
  if (options.dryRun) {
71868
72606
  return true;
71869
72607
  }
71870
- await (0, import_promises7.mkdir)((0, import_node_path22.resolve)(configFile, ".."), { recursive: true });
72608
+ await (0, import_promises7.mkdir)((0, import_node_path23.resolve)(configFile, ".."), { recursive: true });
71871
72609
  await (0, import_promises7.writeFile)(configFile, "plugins:\n enabled:\n - okx-a2a\n");
71872
72610
  console.log(`[update] added Hermes plugins.enabled okx-a2a entry in ${configFile}`);
71873
72611
  return true;
@@ -72107,7 +72845,7 @@ function findFirstEnabledListItem(lines, startIndex, enabledIndent) {
72107
72845
  return null;
72108
72846
  }
72109
72847
  function resolveHermesConfigPath() {
72110
- return (0, import_node_path22.join)(process.env.HERMES_HOME ?? (0, import_node_path22.join)((0, import_node_os7.homedir)(), ".hermes"), "config.yaml");
72848
+ return (0, import_node_path23.join)(process.env.HERMES_HOME ?? (0, import_node_path23.join)((0, import_node_os8.homedir)(), ".hermes"), "config.yaml");
72111
72849
  }
72112
72850
  function lineIndent(line) {
72113
72851
  const match = line.match(/^\s*/);
@@ -72184,22 +72922,18 @@ async function assertGatewayPluginInstalled(target) {
72184
72922
  `okx-a2a ${target} plugin is not installed. Run \`okx-a2a setup ${target}\` first; use \`okx-a2a update ${target}\` only for an existing installation.`
72185
72923
  );
72186
72924
  }
72925
+ function resolveHermesPluginYamlPath() {
72926
+ return (0, import_node_path23.join)(process.env.HERMES_HOME ?? (0, import_node_path23.join)((0, import_node_os8.homedir)(), ".hermes"), "plugins", "platforms", "okx-a2a", "plugin.yaml");
72927
+ }
72187
72928
  async function isGatewayPluginInstalled(target) {
72188
72929
  if (target === "openclaw") {
72189
72930
  return (await getInstalledOpenClawPluginInfo()).installed;
72190
72931
  }
72191
- if ((0, import_node_fs16.existsSync)((0, import_node_path22.join)(process.env.HERMES_HOME ?? (0, import_node_path22.join)((0, import_node_os7.homedir)(), ".hermes"), "plugins", "platforms", "okx-a2a", "plugin.yaml"))) {
72192
- return true;
72193
- }
72194
- return await isGlobalNpmPackageInstalled(UPDATE_PACKAGES.hermes);
72195
- }
72196
- async function isGlobalNpmPackageInstalled(packageName) {
72197
- const result = await runCommandCaptureOptional("npm", ["list", "-g", packageName, "--depth=0"]);
72198
- return result.ok && result.stdout.includes(packageName);
72932
+ return (0, import_node_fs17.existsSync)(resolveHermesPluginYamlPath());
72199
72933
  }
72200
72934
  async function getInstalledGatewayPluginVersion(target) {
72201
72935
  if (target === "hermes") {
72202
- return await getInstalledHermesPluginVersion() ?? await getGlobalNpmPackageVersion(UPDATE_PACKAGES.hermes);
72936
+ return await getInstalledHermesPluginVersion();
72203
72937
  }
72204
72938
  return (await getInstalledOpenClawPluginInfo()).version;
72205
72939
  }
@@ -72282,7 +73016,7 @@ function parsePackageVersionFromText(output) {
72282
73016
  return output.match(/@okxweb3\/a2a-openclaw@([0-9A-Za-z.+-]+)/)?.[1] ?? null;
72283
73017
  }
72284
73018
  async function getInstalledHermesPluginVersion() {
72285
- const pluginYaml = (0, import_node_path22.join)(process.env.HERMES_HOME ?? (0, import_node_path22.join)((0, import_node_os7.homedir)(), ".hermes"), "plugins", "platforms", "okx-a2a", "plugin.yaml");
73019
+ const pluginYaml = (0, import_node_path23.join)(process.env.HERMES_HOME ?? (0, import_node_path23.join)((0, import_node_os8.homedir)(), ".hermes"), "plugins", "platforms", "okx-a2a", "plugin.yaml");
72286
73020
  try {
72287
73021
  const content3 = await (0, import_promises7.readFile)(pluginYaml, "utf8");
72288
73022
  return parsePluginYamlVersion(content3);
@@ -72340,7 +73074,7 @@ async function npmPack(spec, destination) {
72340
73074
  if (!tarballName) {
72341
73075
  throw new Error(`Unable to detect npm pack tarball from output: ${output.trim()}`);
72342
73076
  }
72343
- return (0, import_node_path22.resolve)(destination, (0, import_node_path22.basename)(tarballName));
73077
+ return (0, import_node_path23.resolve)(destination, (0, import_node_path23.basename)(tarballName));
72344
73078
  }
72345
73079
  async function findHermesPluginTarball(distDir) {
72346
73080
  const entries = await (0, import_promises7.readdir)(distDir);
@@ -72348,7 +73082,7 @@ async function findHermesPluginTarball(distDir) {
72348
73082
  if (!tarball) {
72349
73083
  throw new Error(`Hermes npm package did not contain dist/okx-a2a-hermes-plugin-*.tar.gz`);
72350
73084
  }
72351
- return (0, import_node_path22.join)(distDir, tarball);
73085
+ return (0, import_node_path23.join)(distDir, tarball);
72352
73086
  }
72353
73087
  async function findFirstDirectory(parent) {
72354
73088
  const entries = await (0, import_promises7.readdir)(parent, { withFileTypes: true });
@@ -72356,7 +73090,7 @@ async function findFirstDirectory(parent) {
72356
73090
  if (!dir) {
72357
73091
  throw new Error(`No unpacked plugin directory found under ${parent}`);
72358
73092
  }
72359
- return (0, import_node_path22.join)(parent, dir.name);
73093
+ return (0, import_node_path23.join)(parent, dir.name);
72360
73094
  }
72361
73095
  function readOption(args, name2) {
72362
73096
  const index2 = args.indexOf(name2);
@@ -72407,7 +73141,7 @@ async function runCommand(command, args, options = {}) {
72407
73141
  await new Promise((resolvePromise, reject) => {
72408
73142
  const invocation = buildExternalCommandInvocation(command, args);
72409
73143
  const redirect = redirectCommandStdoutToStderr || options.redirectStdoutToStderr === true;
72410
- const child = (0, import_node_child_process5.spawn)(invocation.command, invocation.args, {
73144
+ const child = (0, import_node_child_process6.spawn)(invocation.command, invocation.args, {
72411
73145
  cwd: options.cwd,
72412
73146
  stdio: redirect ? [options.inheritStdin ? "inherit" : "ignore", "pipe", "pipe"] : "inherit",
72413
73147
  windowsVerbatimArguments: invocation.windowsVerbatimArguments
@@ -72451,7 +73185,7 @@ async function runCommand(command, args, options = {}) {
72451
73185
  async function runCommandCapture(command, args) {
72452
73186
  return await new Promise((resolvePromise, reject) => {
72453
73187
  const invocation = buildExternalCommandInvocation(command, args);
72454
- const child = (0, import_node_child_process5.spawn)(invocation.command, invocation.args, {
73188
+ const child = (0, import_node_child_process6.spawn)(invocation.command, invocation.args, {
72455
73189
  stdio: ["ignore", "pipe", "pipe"],
72456
73190
  windowsVerbatimArguments: invocation.windowsVerbatimArguments
72457
73191
  });
@@ -72484,7 +73218,7 @@ ${stderr}`));
72484
73218
  async function runCommandCaptureOptional(command, args) {
72485
73219
  return await new Promise((resolvePromise) => {
72486
73220
  const invocation = buildExternalCommandInvocation(command, args);
72487
- const child = (0, import_node_child_process5.spawn)(invocation.command, invocation.args, {
73221
+ const child = (0, import_node_child_process6.spawn)(invocation.command, invocation.args, {
72488
73222
  stdio: ["ignore", "pipe", "ignore"],
72489
73223
  windowsVerbatimArguments: invocation.windowsVerbatimArguments
72490
73224
  });
@@ -72504,7 +73238,7 @@ async function runCommandCaptureOptional(command, args) {
72504
73238
  async function runCommandCaptureStatus(command, args) {
72505
73239
  return await new Promise((resolvePromise) => {
72506
73240
  const invocation = buildExternalCommandInvocation(command, args);
72507
- const child = (0, import_node_child_process5.spawn)(invocation.command, invocation.args, {
73241
+ const child = (0, import_node_child_process6.spawn)(invocation.command, invocation.args, {
72508
73242
  stdio: ["ignore", "pipe", "pipe"],
72509
73243
  windowsVerbatimArguments: invocation.windowsVerbatimArguments
72510
73244
  });
@@ -72546,15 +73280,15 @@ function buildExternalCommandInvocation(command, args, platform = process.platfo
72546
73280
  function formatExternalCommand(command, args) {
72547
73281
  return [command, ...args].join(" ");
72548
73282
  }
72549
- var import_node_child_process5, import_node_fs16, import_promises7, import_node_os7, import_node_path22, UPDATE_PACKAGES, CODEX_NPM_PACKAGE, OPENCLAW_FORCE_INSTALL_FLAG, OPENCLAW_UNSAFE_INSTALL_FLAG, OKX_A2A_PLUGIN_ID, OPENCLAW_SESSION_DM_SCOPE_CONFIG_PATH, OPENCLAW_SESSION_DM_SCOPE_CONFIG_VALUE, OPENCLAW_PLUGIN_ALLOW_CONFIG_PATH, OPENCLAW_OKX_A2A_CONVERSATION_HOOK_ACCESS_CONFIG_PATH, DEFAULT_AI_PROVIDER_LOGIN_TIMEOUT_MS, SetupBlockedError, redirectCommandStdoutToStderr;
73283
+ var import_node_child_process6, import_node_fs17, import_promises7, import_node_os8, import_node_path23, UPDATE_PACKAGES, CODEX_NPM_PACKAGE, OPENCLAW_FORCE_INSTALL_FLAG, OPENCLAW_UNSAFE_INSTALL_FLAG, OKX_A2A_PLUGIN_ID, OPENCLAW_SESSION_DM_SCOPE_CONFIG_PATH, OPENCLAW_SESSION_DM_SCOPE_CONFIG_VALUE, OPENCLAW_PLUGIN_ALLOW_CONFIG_PATH, OPENCLAW_OKX_A2A_CONVERSATION_HOOK_ACCESS_CONFIG_PATH, DEFAULT_AI_PROVIDER_LOGIN_TIMEOUT_MS, SetupBlockedError, redirectCommandStdoutToStderr;
72550
73284
  var init_update_cli = __esm({
72551
73285
  "src/update-cli.ts"() {
72552
73286
  "use strict";
72553
- import_node_child_process5 = require("node:child_process");
72554
- import_node_fs16 = require("node:fs");
73287
+ import_node_child_process6 = require("node:child_process");
73288
+ import_node_fs17 = require("node:fs");
72555
73289
  import_promises7 = require("node:fs/promises");
72556
- import_node_os7 = require("node:os");
72557
- import_node_path22 = require("node:path");
73290
+ import_node_os8 = require("node:os");
73291
+ import_node_path23 = require("node:path");
72558
73292
  init_ai_command();
72559
73293
  init_win_spawn();
72560
73294
  init_ai_provider();
@@ -72585,160 +73319,6 @@ var init_update_cli = __esm({
72585
73319
  }
72586
73320
  });
72587
73321
 
72588
- // src/win-native-launcher.ts
72589
- var win_native_launcher_exports = {};
72590
- __export(win_native_launcher_exports, {
72591
- NATIVE_LAUNCHER_EXE_NAME: () => NATIVE_LAUNCHER_EXE_NAME,
72592
- buildLauncherEntryJs: () => buildLauncherEntryJs,
72593
- buildSeaConfig: () => buildSeaConfig,
72594
- installWindowsNativeLauncher: () => installWindowsNativeLauncher
72595
- });
72596
- function isPostjectRunnable() {
72597
- try {
72598
- const probe = spawnSyncCompat(POSTJECT_BIN, ["--help"], {
72599
- stdio: "ignore",
72600
- windowsHide: true,
72601
- timeout: 3e4
72602
- });
72603
- return probe.status === 0;
72604
- } catch {
72605
- return false;
72606
- }
72607
- }
72608
- function resolvePostjectCommand() {
72609
- try {
72610
- const cliPath = (0, import_node_module.createRequire)(__filename).resolve("postject/dist/cli.js");
72611
- if ((0, import_node_fs20.existsSync)(cliPath)) {
72612
- return { command: process.execPath, prefixArgs: [cliPath] };
72613
- }
72614
- } catch {
72615
- }
72616
- if (!isPostjectRunnable()) {
72617
- logWinCompat(`${WIN_COMPAT_LOG_PREFIX} native launcher: installing ${POSTJECT_SPEC} globally`);
72618
- const install = spawnSyncCompat("npm", [
72619
- "install",
72620
- "-g",
72621
- POSTJECT_SPEC,
72622
- "--no-audit",
72623
- "--no-fund",
72624
- "--loglevel=error"
72625
- ], { encoding: "utf8", windowsHide: true, timeout: 18e4 });
72626
- if (install.status !== 0 || !isPostjectRunnable()) {
72627
- throw new Error(
72628
- `failed to install ${POSTJECT_SPEC} (needed to build okx-a2a.exe): ${String(install.stderr || install.error?.message || "unknown error").slice(0, 300)}`
72629
- );
72630
- }
72631
- }
72632
- return { command: POSTJECT_BIN, prefixArgs: [] };
72633
- }
72634
- function injectSeaBlob(exePath, blobPath, isMac) {
72635
- const { command, prefixArgs: prefixArgs2 } = resolvePostjectCommand();
72636
- const args = [
72637
- ...prefixArgs2,
72638
- exePath,
72639
- "NODE_SEA_BLOB",
72640
- blobPath,
72641
- "--sentinel-fuse",
72642
- SEA_SENTINEL_FUSE,
72643
- "--overwrite"
72644
- ];
72645
- if (isMac) {
72646
- args.push("--macho-segment-name", "NODE_SEA");
72647
- }
72648
- const result = spawnSyncCompat(command, args, {
72649
- encoding: "utf8",
72650
- windowsHide: true,
72651
- timeout: 12e4
72652
- });
72653
- if (result.status !== 0) {
72654
- throw new Error(
72655
- `postject injection failed: ${String(result.stderr || result.error?.message || `exit ${result.status}`).slice(0, 300)}`
72656
- );
72657
- }
72658
- }
72659
- function buildLauncherEntryJs(cliPath) {
72660
- const target = JSON.stringify(cliPath);
72661
- return [
72662
- 'const { createRequire } = require("node:module");',
72663
- `const nodeRequire = createRequire(${target});`,
72664
- `nodeRequire(${target});`,
72665
- ""
72666
- ].join("\n");
72667
- }
72668
- function buildSeaConfig(entryPath, blobPath) {
72669
- return `${JSON.stringify(
72670
- {
72671
- main: entryPath,
72672
- output: blobPath,
72673
- disableExperimentalSEAWarning: true
72674
- },
72675
- null,
72676
- 2
72677
- )}
72678
- `;
72679
- }
72680
- async function installWindowsNativeLauncher(options) {
72681
- const nodeExe = options.nodeExe ?? process.execPath;
72682
- if (!(0, import_node_fs20.existsSync)(options.cliPath)) {
72683
- throw new Error(`cannot build okx-a2a.exe: CLI entry not found at ${options.cliPath}`);
72684
- }
72685
- if (!(0, import_node_fs20.existsSync)(nodeExe)) {
72686
- throw new Error(`cannot build okx-a2a.exe: node executable not found at ${nodeExe}`);
72687
- }
72688
- const exePath = (0, import_node_path25.join)(options.targetDir, NATIVE_LAUNCHER_EXE_NAME);
72689
- (0, import_node_fs20.mkdirSync)(options.targetDir, { recursive: true });
72690
- const work = (0, import_node_fs20.mkdtempSync)((0, import_node_path25.join)((0, import_node_os9.tmpdir)(), "okx-a2a-sea-"));
72691
- try {
72692
- const entryPath = (0, import_node_path25.join)(work, "launcher-entry.js");
72693
- const blobPath = (0, import_node_path25.join)(work, "okx-a2a.blob");
72694
- const configPath = (0, import_node_path25.join)(work, "sea-config.json");
72695
- (0, import_node_fs20.writeFileSync)(entryPath, buildLauncherEntryJs(options.cliPath), "utf8");
72696
- (0, import_node_fs20.writeFileSync)(configPath, buildSeaConfig(entryPath, blobPath), "utf8");
72697
- (0, import_node_child_process8.execFileSync)(nodeExe, ["--experimental-sea-config", configPath], {
72698
- stdio: "ignore",
72699
- windowsHide: true
72700
- });
72701
- (0, import_node_fs20.copyFileSync)(nodeExe, exePath);
72702
- const isMac = process.platform === "darwin";
72703
- if (isMac) {
72704
- try {
72705
- (0, import_node_child_process8.execFileSync)("codesign", ["--remove-signature", exePath], { stdio: "ignore" });
72706
- } catch {
72707
- }
72708
- }
72709
- injectSeaBlob(exePath, blobPath, isMac);
72710
- if (isMac) {
72711
- try {
72712
- (0, import_node_child_process8.execFileSync)("codesign", ["--sign", "-", exePath], { stdio: "ignore" });
72713
- } catch {
72714
- }
72715
- }
72716
- logWinCompat(
72717
- `${WIN_COMPAT_LOG_PREFIX} native launcher: built ${exePath} from node=${nodeExe} cli=${options.cliPath}`
72718
- );
72719
- return { exePath, cliPath: options.cliPath, nodeExe };
72720
- } finally {
72721
- (0, import_node_fs20.rmSync)(work, { recursive: true, force: true });
72722
- }
72723
- }
72724
- var import_node_child_process8, import_node_fs20, import_node_module, import_node_os9, import_node_path25, SEA_SENTINEL_FUSE, NATIVE_LAUNCHER_EXE_NAME, POSTJECT_SPEC, POSTJECT_BIN;
72725
- var init_win_native_launcher = __esm({
72726
- "src/win-native-launcher.ts"() {
72727
- "use strict";
72728
- import_node_child_process8 = require("node:child_process");
72729
- import_node_fs20 = require("node:fs");
72730
- import_node_module = require("node:module");
72731
- import_node_os9 = require("node:os");
72732
- import_node_path25 = require("node:path");
72733
- init_win_compat();
72734
- init_win_spawn();
72735
- SEA_SENTINEL_FUSE = "NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2";
72736
- NATIVE_LAUNCHER_EXE_NAME = "okx-a2a.exe";
72737
- POSTJECT_SPEC = "postject@1.0.0-alpha.6";
72738
- POSTJECT_BIN = "postject";
72739
- }
72740
- });
72741
-
72742
73322
  // src/index.ts
72743
73323
  var index_exports = {};
72744
73324
  __export(index_exports, {
@@ -72813,12 +73393,14 @@ __export(index_exports, {
72813
73393
  ensureDaemonReady: () => ensureDaemonReady,
72814
73394
  ensureDefaultAiProvider: () => ensureDefaultAiProvider,
72815
73395
  ensureOpenClawOkxA2aPluginConfig: () => ensureOpenClawOkxA2aPluginConfig,
73396
+ ensureWindowsNativeLauncher: () => ensureWindowsNativeLauncher,
72816
73397
  extractAiSessionId: () => extractAiSessionId,
72817
73398
  extractXmtpSentAtMs: () => extractXmtpSentAtMs2,
72818
73399
  findWindowsNativeOkxA2aExe: () => findWindowsNativeOkxA2aExe,
72819
73400
  followFile: () => followFile,
72820
73401
  formatDoctorReportForHumans: () => formatDoctorReportForHumans,
72821
73402
  getDaemonStatus: () => getDaemonStatus,
73403
+ getHermesGatewayPluginStatus: () => getHermesGatewayPluginStatus,
72822
73404
  handleDoctorCommand: () => handleDoctorCommand,
72823
73405
  handleXmtpSendCommand: () => handleXmtpSendCommand,
72824
73406
  hasAiRuntimeMarker: () => hasAiRuntimeMarker,
@@ -72897,502 +73479,7 @@ __export(index_exports, {
72897
73479
  writeAiPermissionPresetToConfig: () => writeAiPermissionPresetToConfig
72898
73480
  });
72899
73481
  module.exports = __toCommonJS(index_exports);
72900
-
72901
- // src/daemon.ts
72902
- var import_node_fs3 = require("node:fs");
72903
- var import_promises2 = require("node:fs/promises");
72904
- var import_node_child_process = require("node:child_process");
72905
- var import_node_path5 = require("node:path");
72906
- init_paths();
72907
- init_session_store();
72908
-
72909
- // src/daemon-lock.ts
72910
- var import_promises = require("node:fs/promises");
72911
- var import_node_path4 = require("node:path");
72912
- init_paths();
72913
- init_a2a_paths();
72914
- var OWNER_FILE = "owner.json";
72915
- var EMPTY_LOCK_STALE_MS = 1e4;
72916
- var DAEMON_CAPABILITY_AI_DISPATCH = "ai-dispatch";
72917
- var DAEMON_CAPABILITIES = [
72918
- DAEMON_CAPABILITY_AI_DISPATCH
72919
- ];
72920
- function isProcessAlive(pid) {
72921
- try {
72922
- process.kill(pid, 0);
72923
- return true;
72924
- } catch (err2) {
72925
- return err2.code === "EPERM";
72926
- }
72927
- }
72928
- function ownerPath(lockPath) {
72929
- return (0, import_node_path4.join)(lockPath, OWNER_FILE);
72930
- }
72931
- async function readDaemonLock(lockPath) {
72932
- let metadata = null;
72933
- try {
72934
- const raw = await (0, import_promises.readFile)(ownerPath(lockPath), "utf8");
72935
- metadata = JSON.parse(raw);
72936
- } catch (err2) {
72937
- const code2 = err2.code;
72938
- if (code2 === "ENOENT") {
72939
- try {
72940
- const info = await (0, import_promises.stat)(lockPath);
72941
- const stale = Date.now() - info.mtimeMs > EMPTY_LOCK_STALE_MS;
72942
- return { metadata: null, running: !stale, stale, path: lockPath };
72943
- } catch (statErr) {
72944
- const statCode = statErr.code;
72945
- if (statCode === "ENOENT") {
72946
- return { metadata: null, running: false, stale: false, path: lockPath };
72947
- }
72948
- throw statErr;
72949
- }
72950
- }
72951
- if (err2 instanceof SyntaxError) {
72952
- return { metadata: null, running: false, stale: true, path: lockPath };
72953
- }
72954
- throw err2;
72955
- }
72956
- const running = Number.isInteger(metadata.pid) && metadata.pid > 0 && isProcessAlive(metadata.pid);
72957
- return { metadata, running, stale: !running, path: lockPath };
72958
- }
72959
- async function markDaemonReady(lockPath) {
72960
- const current = await readDaemonLock(lockPath);
72961
- const metadata = current.metadata;
72962
- if (!metadata || metadata.pid !== process.pid) {
72963
- return;
72964
- }
72965
- await (0, import_promises.writeFile)(ownerPath(lockPath), `${JSON.stringify({
72966
- ...metadata,
72967
- ready: true,
72968
- readyAt: (/* @__PURE__ */ new Date()).toISOString()
72969
- }, null, 2)}
72970
- `, "utf8");
72971
- }
72972
- async function removeLock(lockPath) {
72973
- await (0, import_promises.rm)(lockPath, { recursive: true, force: true });
72974
- }
72975
- async function acquireDaemonLock(paths, entry) {
72976
- const metadata = {
72977
- pid: process.pid,
72978
- startedAt: (/* @__PURE__ */ new Date()).toISOString(),
72979
- cwd: process.cwd(),
72980
- entry,
72981
- homeDir: paths.homeDir,
72982
- capabilities: DAEMON_CAPABILITIES,
72983
- ready: false
72984
- };
72985
- ensureTaskDir(paths.runDir);
72986
- for (let attempt = 0; attempt < 2; attempt += 1) {
72987
- try {
72988
- await (0, import_promises.mkdir)(paths.daemonLockPath, { mode: A2A_TASK_DIR_MODE });
72989
- await chmodBestEffort(paths.daemonLockPath, A2A_TASK_DIR_MODE);
72990
- await (0, import_promises.writeFile)(ownerPath(paths.daemonLockPath), `${JSON.stringify(metadata, null, 2)}
72991
- `, "utf8");
72992
- return {
72993
- metadata,
72994
- release: async () => {
72995
- const current = await readDaemonLock(paths.daemonLockPath);
72996
- if (current.metadata?.pid === process.pid) {
72997
- await removeLock(paths.daemonLockPath);
72998
- }
72999
- }
73000
- };
73001
- } catch (err2) {
73002
- const code2 = err2.code;
73003
- if (code2 !== "EEXIST") {
73004
- throw err2;
73005
- }
73006
- const current = await readDaemonLock(paths.daemonLockPath);
73007
- if (current.running) {
73008
- return null;
73009
- }
73010
- if (!current.stale) {
73011
- return null;
73012
- }
73013
- await removeLock(paths.daemonLockPath);
73014
- }
73015
- }
73016
- return null;
73017
- }
73018
- async function chmodBestEffort(path, mode) {
73019
- try {
73020
- await (0, import_promises.chmod)(path, mode);
73021
- } catch (err2) {
73022
- const code2 = err2.code;
73023
- if (code2 !== "EPERM" && code2 !== "EACCES") {
73024
- throw err2;
73025
- }
73026
- }
73027
- }
73028
-
73029
- // src/daemon.ts
73030
- var STOP_GRACE_MS = 5e3;
73031
- var FORCE_KILL_GRACE_MS = 5e3;
73032
- var START_EXIT_CHECK_MS = 750;
73033
- var DEFAULT_READY_TIMEOUT_MS = 12e4;
73034
- var READY_POLL_MS = 250;
73035
- var DAEMON_READY_TIMEOUT_ENV = "OKX_A2A_DAEMON_READY_TIMEOUT_MS";
73036
- async function readPid(pidPath) {
73037
- try {
73038
- const raw = await (0, import_promises2.readFile)(pidPath, "utf8");
73039
- const pid = Number.parseInt(raw.trim(), 10);
73040
- return Number.isInteger(pid) && pid > 0 ? pid : null;
73041
- } catch (err2) {
73042
- const code2 = err2.code;
73043
- if (code2 === "ENOENT") {
73044
- return null;
73045
- }
73046
- throw err2;
73047
- }
73048
- }
73049
- async function removePid(pidPath) {
73050
- try {
73051
- await (0, import_promises2.unlink)(pidPath);
73052
- } catch (err2) {
73053
- const code2 = err2.code;
73054
- if (code2 !== "ENOENT") {
73055
- throw err2;
73056
- }
73057
- }
73058
- }
73059
- async function ensureDaemonDirs(homeDir) {
73060
- const paths = resolveTaskPaths(homeDir);
73061
- ensureTaskDir(paths.jobsDir);
73062
- ensureTaskDir(paths.runDir);
73063
- ensureTaskDir(paths.logsDir);
73064
- ensureTaskDir(paths.commandsDir);
73065
- ensureTaskDir(paths.downloadsDir);
73066
- ensureTaskDir(paths.xmtpDir);
73067
- ensureTaskDir(paths.sqliteDir);
73068
- return paths;
73069
- }
73070
- async function ensureAiWorkspace(paths) {
73071
- const aiWorkingDir = paths.workspaceDir;
73072
- await (0, import_promises2.rm)(aiWorkingDir, { recursive: true, force: true });
73073
- ensureTaskDir(aiWorkingDir);
73074
- return aiWorkingDir;
73075
- }
73076
- async function waitForImmediateExit(child, timeoutMs) {
73077
- return await new Promise((resolve6) => {
73078
- let timer;
73079
- const onExit = () => {
73080
- clearTimeout(timer);
73081
- resolve6(true);
73082
- };
73083
- timer = setTimeout(() => {
73084
- child.off("exit", onExit);
73085
- resolve6(false);
73086
- }, timeoutMs);
73087
- child.once("exit", onExit);
73088
- });
73089
- }
73090
- async function getDaemonStatus(homeDir) {
73091
- const paths = resolveTaskPaths(homeDir);
73092
- const pid = await readPid(paths.pidPath);
73093
- const lock = await readDaemonLock(paths.daemonLockPath);
73094
- const lockPid = lock.metadata?.pid ?? null;
73095
- const lockReadyStateKnown = !!lock.metadata && (typeof lock.metadata.ready === "boolean" || typeof lock.metadata.readyAt === "string");
73096
- const lockReady = lockReadyStateKnown ? lock.metadata?.ready === true || typeof lock.metadata?.readyAt === "string" : true;
73097
- if (lock.running) {
73098
- return {
73099
- running: true,
73100
- pid: lockPid ?? pid,
73101
- stale: false,
73102
- capabilities: lock.metadata?.capabilities ?? [],
73103
- ready: lockReady,
73104
- readyAt: lock.metadata?.readyAt ?? null,
73105
- readyStateKnown: lockReadyStateKnown,
73106
- pidPath: paths.pidPath,
73107
- lockPath: paths.daemonLockPath,
73108
- lockPid,
73109
- lockStale: false
73110
- };
73111
- }
73112
- if (!pid) {
73113
- return {
73114
- running: false,
73115
- pid: null,
73116
- stale: lock.stale,
73117
- capabilities: [],
73118
- ready: false,
73119
- readyAt: null,
73120
- readyStateKnown: false,
73121
- pidPath: paths.pidPath,
73122
- lockPath: paths.daemonLockPath,
73123
- lockPid,
73124
- lockStale: lock.stale
73125
- };
73126
- }
73127
- const running = isProcessAlive(pid);
73128
- return {
73129
- running,
73130
- pid,
73131
- stale: !running || lock.stale,
73132
- capabilities: running ? lock.metadata?.capabilities ?? [] : [],
73133
- ready: running && !lockReadyStateKnown ? true : running && lockReady,
73134
- readyAt: running ? lock.metadata?.readyAt ?? null : null,
73135
- readyStateKnown: running && lockReadyStateKnown,
73136
- pidPath: paths.pidPath,
73137
- lockPath: paths.daemonLockPath,
73138
- lockPid,
73139
- lockStale: lock.stale
73140
- };
73141
- }
73142
- async function startDaemon(homeDir) {
73143
- const paths = await ensureDaemonDirs(homeDir);
73144
- const aiWorkingDir = await ensureAiWorkspace(paths);
73145
- const current = await getDaemonStatus(homeDir);
73146
- if (current.running) {
73147
- return {
73148
- ...current,
73149
- started: false,
73150
- logPath: paths.listenerLogPath
73151
- };
73152
- }
73153
- if (current.stale) {
73154
- await removePid(paths.pidPath);
73155
- }
73156
- const store = new SessionStore({ homeDir });
73157
- try {
73158
- store.setSetting("ai_working_dir", aiWorkingDir);
73159
- store.resetGlobalSession(SYSTEM_NOTIFICATION_SESSION_KEY);
73160
- } finally {
73161
- store.close();
73162
- }
73163
- const logFd = (0, import_node_fs3.openSync)(paths.listenerLogPath, "a");
73164
- const entry = process.env.OKX_AGENT_TASK_CLI_PATH || (0, import_node_path5.join)(__dirname, "cli.js");
73165
- const daemonCwd = (0, import_node_path5.join)(__dirname, "..");
73166
- const child = (0, import_node_child_process.spawn)(process.execPath, [entry, "run"], {
73167
- cwd: daemonCwd,
73168
- detached: true,
73169
- // win32: keep the detached daemon from flashing/holding a console window.
73170
- // Ignored on every non-win32 platform.
73171
- windowsHide: true,
73172
- env: {
73173
- ...process.env,
73174
- OKX_AGENT_TASK_HOME: paths.homeDir,
73175
- OKX_AGENT_TASK_DAEMON: "1",
73176
- OKX_A2A_AI_CWD: aiWorkingDir,
73177
- OKX_AGENT_TASK_AI_CWD: aiWorkingDir
73178
- },
73179
- stdio: ["ignore", logFd, logFd]
73180
- });
73181
- (0, import_node_fs3.closeSync)(logFd);
73182
- child.unref();
73183
- await (0, import_promises2.writeFile)(paths.pidPath, `${child.pid ?? ""}
73184
- `, "utf8");
73185
- if (await waitForImmediateExit(child, START_EXIT_CHECK_MS)) {
73186
- const status = await getDaemonStatus(homeDir);
73187
- if (status.running && status.lockPid) {
73188
- await (0, import_promises2.writeFile)(paths.pidPath, `${status.lockPid}
73189
- `, "utf8");
73190
- } else {
73191
- await removePid(paths.pidPath);
73192
- }
73193
- return {
73194
- ...status,
73195
- started: false,
73196
- logPath: paths.listenerLogPath
73197
- };
73198
- }
73199
- return {
73200
- running: true,
73201
- pid: child.pid ?? null,
73202
- stale: false,
73203
- capabilities: DAEMON_CAPABILITIES,
73204
- ready: false,
73205
- readyAt: null,
73206
- readyStateKnown: true,
73207
- pidPath: paths.pidPath,
73208
- lockPath: paths.daemonLockPath,
73209
- lockPid: child.pid ?? null,
73210
- lockStale: false,
73211
- started: true,
73212
- logPath: paths.listenerLogPath
73213
- };
73214
- }
73215
- async function waitForExit(pid, timeoutMs) {
73216
- const deadline = Date.now() + timeoutMs;
73217
- while (Date.now() < deadline) {
73218
- if (!isProcessAlive(pid)) {
73219
- return true;
73220
- }
73221
- await new Promise((resolve6) => setTimeout(resolve6, 100));
73222
- }
73223
- return !isProcessAlive(pid);
73224
- }
73225
- function signalProcess(pid, signal) {
73226
- try {
73227
- process.kill(pid, signal);
73228
- return true;
73229
- } catch (err2) {
73230
- const code2 = err2.code;
73231
- if (code2 === "ESRCH") {
73232
- return false;
73233
- }
73234
- throw err2;
73235
- }
73236
- }
73237
- async function stopDaemon(homeDir) {
73238
- const paths = resolveTaskPaths(homeDir);
73239
- const current = await getDaemonStatus(homeDir);
73240
- if (!current.pid) {
73241
- return { ...current, stopped: false };
73242
- }
73243
- if (!current.running) {
73244
- await removePid(paths.pidPath);
73245
- return {
73246
- running: false,
73247
- pid: current.pid,
73248
- stale: false,
73249
- capabilities: [],
73250
- ready: false,
73251
- readyAt: null,
73252
- readyStateKnown: false,
73253
- pidPath: paths.pidPath,
73254
- lockPath: paths.daemonLockPath,
73255
- lockPid: current.lockPid,
73256
- lockStale: current.lockStale,
73257
- stopped: false
73258
- };
73259
- }
73260
- const signalled = signalProcess(current.pid, "SIGTERM");
73261
- let forced = false;
73262
- let exited = !signalled || await waitForExit(current.pid, STOP_GRACE_MS);
73263
- if (!exited) {
73264
- forced = true;
73265
- const killed = signalProcess(current.pid, "SIGKILL");
73266
- exited = !killed || await waitForExit(current.pid, FORCE_KILL_GRACE_MS);
73267
- }
73268
- if (exited) {
73269
- await removePid(paths.pidPath);
73270
- }
73271
- return {
73272
- running: !exited,
73273
- pid: current.pid,
73274
- stale: false,
73275
- capabilities: exited ? [] : current.capabilities,
73276
- ready: !exited && current.ready,
73277
- readyAt: !exited ? current.readyAt : null,
73278
- readyStateKnown: !exited && current.readyStateKnown,
73279
- pidPath: paths.pidPath,
73280
- lockPath: paths.daemonLockPath,
73281
- lockPid: current.lockPid,
73282
- lockStale: current.lockStale,
73283
- stopped: exited,
73284
- forced
73285
- };
73286
- }
73287
- async function ensureDaemonReady(options = {}) {
73288
- const paths = resolveTaskPaths(options.homeDir);
73289
- const commandName = options.commandName ?? "command";
73290
- const timeoutMs = options.timeoutMs ?? readReadyTimeoutMs(options.env ?? process.env);
73291
- let status = await getDaemonStatus(options.homeDir);
73292
- let started = false;
73293
- let logPath = paths.listenerLogPath;
73294
- if (!status.running) {
73295
- options.stderr?.write(`[okx-a2a] ${commandName} requires the daemon; starting daemon...
73296
- `);
73297
- const startResult = await startDaemon(options.homeDir);
73298
- started = startResult.started;
73299
- logPath = startResult.logPath;
73300
- status = startResult;
73301
- if (!status.running) {
73302
- throw new Error(
73303
- `${commandName} requires the daemon, but automatic daemon start failed. Check ${logPath} or run \`okx-a2a daemon restart\`.`
73304
- );
73305
- }
73306
- status = await waitForDaemonReady({
73307
- homeDir: options.homeDir,
73308
- timeoutMs,
73309
- requiredCapabilities: options.requiredCapabilities,
73310
- requireKnownReadyState: true,
73311
- logPath,
73312
- commandName
73313
- });
73314
- options.stderr?.write(`[okx-a2a] daemon ready pid=${status.pid ?? "(unknown)"} log=${logPath}
73315
- `);
73316
- } else if (status.readyStateKnown && !status.ready) {
73317
- status = await waitForDaemonReady({
73318
- homeDir: options.homeDir,
73319
- timeoutMs,
73320
- requiredCapabilities: options.requiredCapabilities,
73321
- requireKnownReadyState: false,
73322
- logPath,
73323
- commandName
73324
- });
73325
- }
73326
- assertRequiredCapabilities(status, options.requiredCapabilities, commandName);
73327
- return {
73328
- ...status,
73329
- started,
73330
- logPath
73331
- };
73332
- }
73333
- async function waitForDaemonReady(options) {
73334
- const deadline = Date.now() + Math.max(0, options.timeoutMs);
73335
- let lastStatus = await getDaemonStatus(options.homeDir);
73336
- while (Date.now() <= deadline) {
73337
- const status = await getDaemonStatus(options.homeDir);
73338
- lastStatus = status;
73339
- if (!status.running) {
73340
- if (status.stale) {
73341
- throw new Error(
73342
- `${options.commandName} requires the daemon, but the daemon exited before becoming ready. Check ${options.logPath} or run \`okx-a2a daemon restart\`.`
73343
- );
73344
- }
73345
- } else if (isReadyForCommand(status, options.requiredCapabilities, options.requireKnownReadyState)) {
73346
- return status;
73347
- } else if (status.ready && findMissingCapabilities(status, options.requiredCapabilities).length > 0) {
73348
- assertRequiredCapabilities(status, options.requiredCapabilities, options.commandName);
73349
- }
73350
- await sleep(Math.min(READY_POLL_MS, Math.max(1, deadline - Date.now() + 1)));
73351
- }
73352
- const missing = findMissingCapabilities(lastStatus, options.requiredCapabilities);
73353
- const capabilitySuffix = missing.length > 0 ? ` missingCapabilities=${missing.join(",")}` : "";
73354
- throw new Error(
73355
- `${options.commandName} requires the daemon, but it did not become ready within ${options.timeoutMs}ms${capabilitySuffix}. Check ${options.logPath} or run \`okx-a2a daemon restart\`.`
73356
- );
73357
- }
73358
- function isReadyForCommand(status, requiredCapabilities, requireKnownReadyState = false) {
73359
- if (!status.running) {
73360
- return false;
73361
- }
73362
- if (requireKnownReadyState && !status.readyStateKnown) {
73363
- return false;
73364
- }
73365
- if (status.readyStateKnown && !status.ready) {
73366
- return false;
73367
- }
73368
- return findMissingCapabilities(status, requiredCapabilities).length === 0;
73369
- }
73370
- function assertRequiredCapabilities(status, requiredCapabilities, commandName) {
73371
- const missing = findMissingCapabilities(status, requiredCapabilities);
73372
- if (missing.length === 0) {
73373
- return;
73374
- }
73375
- throw new Error(
73376
- `${commandName} requires a daemon with ${missing.join(",")} support. Run \`okx-a2a daemon restart\` first.`
73377
- );
73378
- }
73379
- function findMissingCapabilities(status, requiredCapabilities) {
73380
- if (!requiredCapabilities || requiredCapabilities.length === 0) {
73381
- return [];
73382
- }
73383
- return requiredCapabilities.filter((capability) => !status.capabilities.includes(capability));
73384
- }
73385
- function readReadyTimeoutMs(env) {
73386
- const raw = env[DAEMON_READY_TIMEOUT_ENV]?.trim();
73387
- if (!raw) {
73388
- return DEFAULT_READY_TIMEOUT_MS;
73389
- }
73390
- const parsed = Number(raw);
73391
- return Number.isFinite(parsed) && parsed > 0 ? parsed : DEFAULT_READY_TIMEOUT_MS;
73392
- }
73393
- function sleep(ms) {
73394
- return new Promise((resolve6) => setTimeout(resolve6, ms));
73395
- }
73482
+ init_daemon();
73396
73483
 
73397
73484
  // src/ai-runner.ts
73398
73485
  init_log();
@@ -73879,6 +73966,7 @@ var LogEvent = {
73879
73966
  ONCHAINOS_CLI_ERROR: "Onchainos CLI error",
73880
73967
  HEARTBEAT_FAILED: "Heartbeat failed",
73881
73968
  HEARTBEAT_SKIPPED: "Heartbeat skipped",
73969
+ HEARTBEAT_GATEWAY_CHECK_FAILED: "Heartbeat gateway check failed",
73882
73970
  MESSAGE_PARSE_FAILED: "Message parse failed",
73883
73971
  MESSAGE_HANDLER_ERROR: "Message handler error",
73884
73972
  OFFLINE_REPLAY_FAILED: "Offline replay failed",
@@ -89316,7 +89404,7 @@ function buildConnectParams(config, instanceId, protocolVersion) {
89316
89404
  client: {
89317
89405
  id: "gateway-client",
89318
89406
  displayName: "okx-a2a-node",
89319
- version: "0.1.5",
89407
+ version: "0.1.6",
89320
89408
  platform: "node",
89321
89409
  mode: "backend",
89322
89410
  instanceId
@@ -89327,7 +89415,7 @@ function buildConnectParams(config, instanceId, protocolVersion) {
89327
89415
  commands: [],
89328
89416
  permissions: {},
89329
89417
  locale: Intl.DateTimeFormat().resolvedOptions().locale || "en-US",
89330
- userAgent: `okx-a2a-node/${"0.1.5"}`,
89418
+ userAgent: `okx-a2a-node/${"0.1.6"}`,
89331
89419
  auth: {
89332
89420
  ...config.token ? { token: config.token } : {},
89333
89421
  ...config.password ? { password: config.password } : {}
@@ -93791,13 +93879,14 @@ function userWatchEventDeliveredSentryExtra(event) {
93791
93879
  }
93792
93880
 
93793
93881
  // src/listener.ts
93882
+ init_daemon_lock();
93794
93883
  init_ai_provider();
93795
93884
 
93796
93885
  // ../core/src/sentry-config.ts
93797
93886
  var environment = process.env.SENTRY_ENV === "dev" ? "dev" : "prod";
93798
93887
  var SENTRY_CONFIG = {
93799
93888
  projectName: "okx/openclaw-okx-a2a-extension",
93800
- release: "0.1.5",
93889
+ release: "0.1.6",
93801
93890
  environment
93802
93891
  };
93803
93892
 
@@ -93837,20 +93926,31 @@ async function isGatewayAvailableForHeartbeat(options) {
93837
93926
  }
93838
93927
  return isHermesGatewayPluginEnabled({ env: options.env });
93839
93928
  }
93840
- async function isHermesGatewayPluginEnabled(options = {}) {
93929
+ async function getHermesGatewayPluginStatus(options = {}) {
93841
93930
  const env = options.env ?? process.env;
93842
- if (options.requireGatewayRuntime && detectGatewayInvocation(env) !== "hermes") {
93843
- return false;
93844
- }
93845
93931
  const hermesHome = env.HERMES_HOME?.trim() || (0, import_node_path21.join)((0, import_node_os6.homedir)(), ".hermes");
93846
- if (!(0, import_node_fs15.existsSync)((0, import_node_path21.join)(hermesHome, "plugins", "platforms", "okx-a2a", "plugin.yaml"))) {
93847
- return false;
93932
+ const pluginYamlPath = (0, import_node_path21.join)(hermesHome, "plugins", "platforms", "okx-a2a", "plugin.yaml");
93933
+ if (!(0, import_node_fs15.existsSync)(pluginYamlPath)) {
93934
+ return { enabled: false, reason: "plugin_yaml_missing", hermesHome, checkedPath: pluginYamlPath };
93848
93935
  }
93936
+ const configPath = (0, import_node_path21.join)(hermesHome, "config.yaml");
93937
+ let content3;
93849
93938
  try {
93850
- return hermesConfigEnablesOkxA2a(await (0, import_promises6.readFile)((0, import_node_path21.join)(hermesHome, "config.yaml"), "utf8"));
93939
+ content3 = await (0, import_promises6.readFile)(configPath, "utf8");
93851
93940
  } catch {
93941
+ return { enabled: false, reason: "config_read_error", hermesHome, checkedPath: configPath };
93942
+ }
93943
+ if (!hermesConfigEnablesOkxA2a(content3)) {
93944
+ return { enabled: false, reason: "config_disabled", hermesHome, checkedPath: configPath };
93945
+ }
93946
+ return { enabled: true, hermesHome, checkedPath: pluginYamlPath };
93947
+ }
93948
+ async function isHermesGatewayPluginEnabled(options = {}) {
93949
+ const env = options.env ?? process.env;
93950
+ if (options.requireGatewayRuntime && detectGatewayInvocation(env) !== "hermes") {
93852
93951
  return false;
93853
93952
  }
93953
+ return (await getHermesGatewayPluginStatus({ env })).enabled;
93854
93954
  }
93855
93955
  function hermesConfigEnablesOkxA2a(content3) {
93856
93956
  let inPlugins = false;
@@ -94024,12 +94124,12 @@ async function runListenerWithLock(options, paths) {
94024
94124
  }));
94025
94125
  }
94026
94126
  });
94027
- service.setPluginVersion("0.1.5");
94127
+ service.setPluginVersion("0.1.6");
94028
94128
  await service.init();
94029
94129
  const pluginVersionStatus = service.pluginVersionStatus;
94030
94130
  if (pluginVersionStatus.unavailable) {
94031
94131
  throw new Error(
94032
- `@okxweb3/a2a-node v${"0.1.5"} is below the required minimum v${pluginVersionStatus.minVersion}`
94132
+ `@okxweb3/a2a-node v${"0.1.6"} is below the required minimum v${pluginVersionStatus.minVersion}`
94033
94133
  );
94034
94134
  }
94035
94135
  const systemConfig = service.getSystemConfig();
@@ -94047,7 +94147,7 @@ async function runListenerWithLock(options, paths) {
94047
94147
  onchainosAgentId: "*",
94048
94148
  reason: "system-config missing sentryDsn",
94049
94149
  pluginId: "@okxweb3/a2a-node",
94050
- pluginVersion: "0.1.5"
94150
+ pluginVersion: "0.1.6"
94051
94151
  });
94052
94152
  }
94053
94153
  logWithTimestamp(
@@ -94087,7 +94187,28 @@ async function runListenerWithLock(options, paths) {
94087
94187
  const hasActiveAgents = service.getClients().size > 0;
94088
94188
  let shouldHeartbeat = hasActiveAgents;
94089
94189
  const heartbeatProvider = resolveConfiguredAiProvider({ store: sessionStore }) ?? detectGatewayInvocation();
94090
- if (hasActiveAgents) {
94190
+ if (hasActiveAgents && heartbeatProvider === "hermes") {
94191
+ const hermesStatus = await getHermesGatewayPluginStatus();
94192
+ if (!hermesStatus.enabled) {
94193
+ logWithTimestamp(
94194
+ `[okx-agent-task] provider=hermes gateway check failed (${hermesStatus.reason}), sending heartbeat anyway`
94195
+ );
94196
+ logger.error(
94197
+ LogEvent.HEARTBEAT_GATEWAY_CHECK_FAILED,
94198
+ new Error(`heartbeat gateway check failed: provider=hermes reason=${hermesStatus.reason}`),
94199
+ {
94200
+ component: "node_listener",
94201
+ stage: "sync_tick",
94202
+ reason: hermesStatus.reason ?? "unknown",
94203
+ provider: "hermes",
94204
+ hermesHome: hermesStatus.hermesHome,
94205
+ checkedPath: hermesStatus.checkedPath,
94206
+ chainIndex: ONCHAINOS_CHAIN_INDEX,
94207
+ communicationClass: "gateway_or_plugin"
94208
+ }
94209
+ );
94210
+ }
94211
+ } else if (hasActiveAgents) {
94091
94212
  const gatewayAvailable = await isGatewayAvailableForHeartbeat({
94092
94213
  provider: heartbeatProvider
94093
94214
  });
@@ -94409,7 +94530,7 @@ init_update_cli();
94409
94530
  init_win_spawn();
94410
94531
 
94411
94532
  // src/log-tail.ts
94412
- var import_node_fs17 = require("node:fs");
94533
+ var import_node_fs18 = require("node:fs");
94413
94534
  var import_promises8 = require("node:fs/promises");
94414
94535
  var import_node_string_decoder = require("node:string_decoder");
94415
94536
  init_win_spawn();
@@ -94533,7 +94654,7 @@ async function followFile(filePath, onData, options = {}) {
94533
94654
  void check();
94534
94655
  }, pollIntervalMs);
94535
94656
  try {
94536
- watcher = (0, import_node_fs17.watch)(filePath, () => {
94657
+ watcher = (0, import_node_fs18.watch)(filePath, () => {
94537
94658
  void check();
94538
94659
  });
94539
94660
  watcher.on("error", (error) => {
@@ -94599,8 +94720,6 @@ init_ai_provider();
94599
94720
  init_update_cli();
94600
94721
 
94601
94722
  // src/doctor-cli.ts
94602
- var import_node_fs21 = require("node:fs");
94603
- var import_node_os10 = require("node:os");
94604
94723
  var import_node_path26 = require("node:path");
94605
94724
  init_log();
94606
94725
  init_win_compat();
@@ -94608,18 +94727,18 @@ init_ai_command();
94608
94727
  init_ai_provider();
94609
94728
 
94610
94729
  // src/autostart.ts
94611
- var import_node_child_process7 = require("node:child_process");
94612
- var import_node_fs19 = require("node:fs");
94730
+ var import_node_child_process8 = require("node:child_process");
94731
+ var import_node_fs20 = require("node:fs");
94613
94732
  var import_promises10 = require("node:fs/promises");
94614
- var import_node_os8 = require("node:os");
94615
- var import_node_path24 = require("node:path");
94733
+ var import_node_os9 = require("node:os");
94734
+ var import_node_path25 = require("node:path");
94616
94735
  var import_node_util2 = require("node:util");
94617
94736
 
94618
94737
  // src/autostart-windows.ts
94619
- var import_node_child_process6 = require("node:child_process");
94620
- var import_node_fs18 = require("node:fs");
94738
+ var import_node_child_process7 = require("node:child_process");
94739
+ var import_node_fs19 = require("node:fs");
94621
94740
  var import_promises9 = require("node:fs/promises");
94622
- var import_node_path23 = require("node:path");
94741
+ var import_node_path24 = require("node:path");
94623
94742
  init_log();
94624
94743
  init_paths();
94625
94744
  init_win_spawn();
@@ -94630,10 +94749,10 @@ var SCHTASKS_TIMEOUT_MS = 15e3;
94630
94749
  var LOG_SNIPPET_LIMIT = 500;
94631
94750
  function resolveWindowsAutostartPaths(homeDir) {
94632
94751
  const resolvedHome = homeDir ?? resolveTaskPaths().homeDir;
94633
- const autostartDir = (0, import_node_path23.join)(resolvedHome, "autostart");
94752
+ const autostartDir = (0, import_node_path24.join)(resolvedHome, "autostart");
94634
94753
  return {
94635
94754
  autostartDir,
94636
- vbsPath: (0, import_node_path23.join)(autostartDir, VBS_FILE_NAME)
94755
+ vbsPath: (0, import_node_path24.join)(autostartDir, VBS_FILE_NAME)
94637
94756
  };
94638
94757
  }
94639
94758
  function escapeVbsString(value) {
@@ -94665,7 +94784,7 @@ function buildAutostartVbs(options) {
94665
94784
  `;
94666
94785
  }
94667
94786
  function isWindowsElevated() {
94668
- const result = (0, import_node_child_process6.spawnSync)("net", ["session"], {
94787
+ const result = (0, import_node_child_process7.spawnSync)("net", ["session"], {
94669
94788
  windowsHide: true,
94670
94789
  encoding: "utf8",
94671
94790
  timeout: 5e3,
@@ -94710,10 +94829,10 @@ function resolveWindowsCliPath() {
94710
94829
  logWinCompat(`${WIN_COMPAT_LOG_PREFIX} autostart: process.argv[1] is empty, cannot resolve okx-a2a CLI path`);
94711
94830
  throw new Error("Unable to resolve current okx-a2a CLI path");
94712
94831
  }
94713
- return (0, import_node_path23.resolve)(entry);
94832
+ return (0, import_node_path24.resolve)(entry);
94714
94833
  }
94715
94834
  function runSchtasks(operation, args) {
94716
- const result = (0, import_node_child_process6.spawnSync)(SCHTASKS_BIN, args, {
94835
+ const result = (0, import_node_child_process7.spawnSync)(SCHTASKS_BIN, args, {
94717
94836
  windowsHide: true,
94718
94837
  encoding: "utf8",
94719
94838
  timeout: SCHTASKS_TIMEOUT_MS
@@ -94751,10 +94870,10 @@ async function installWindowsAutostart() {
94751
94870
  const execPath = process.execPath;
94752
94871
  const cliPath = resolveWindowsCliPath();
94753
94872
  const pathValue = process.env.PATH?.trim() || "";
94754
- if (!(0, import_node_fs18.existsSync)(execPath)) {
94873
+ if (!(0, import_node_fs19.existsSync)(execPath)) {
94755
94874
  throw new Error(`autostart: node executable not found at ${execPath}`);
94756
94875
  }
94757
- if (!(0, import_node_fs18.existsSync)(cliPath)) {
94876
+ if (!(0, import_node_fs19.existsSync)(cliPath)) {
94758
94877
  throw new Error(`autostart: okx-a2a CLI entry not found at ${cliPath}`);
94759
94878
  }
94760
94879
  await (0, import_promises9.mkdir)(paths.autostartDir, { recursive: true });
@@ -94789,22 +94908,22 @@ function isWindowsAutostartInstalled() {
94789
94908
 
94790
94909
  // src/autostart.ts
94791
94910
  init_paths();
94792
- var execFileAsync2 = (0, import_node_util2.promisify)(import_node_child_process7.execFile);
94911
+ var execFileAsync2 = (0, import_node_util2.promisify)(import_node_child_process8.execFile);
94793
94912
  var SERVICE_NAME = "okx-a2a.service";
94794
94913
  var LAUNCHD_LABEL = "com.okx.a2a";
94795
94914
  var LAUNCHD_PLIST_NAME = `${LAUNCHD_LABEL}.plist`;
94796
- function resolveSystemdAutostartPaths(home = (0, import_node_os8.homedir)()) {
94797
- const serviceDir = (0, import_node_path24.join)(home, ".config", "systemd", "user");
94915
+ function resolveSystemdAutostartPaths(home = (0, import_node_os9.homedir)()) {
94916
+ const serviceDir = (0, import_node_path25.join)(home, ".config", "systemd", "user");
94798
94917
  return {
94799
94918
  serviceDir,
94800
- servicePath: (0, import_node_path24.join)(serviceDir, SERVICE_NAME)
94919
+ servicePath: (0, import_node_path25.join)(serviceDir, SERVICE_NAME)
94801
94920
  };
94802
94921
  }
94803
- function resolveLaunchdAutostartPaths(home = (0, import_node_os8.homedir)()) {
94804
- const agentDir = (0, import_node_path24.join)(home, "Library", "LaunchAgents");
94922
+ function resolveLaunchdAutostartPaths(home = (0, import_node_os9.homedir)()) {
94923
+ const agentDir = (0, import_node_path25.join)(home, "Library", "LaunchAgents");
94805
94924
  return {
94806
94925
  agentDir,
94807
- plistPath: (0, import_node_path24.join)(agentDir, LAUNCHD_PLIST_NAME)
94926
+ plistPath: (0, import_node_path25.join)(agentDir, LAUNCHD_PLIST_NAME)
94808
94927
  };
94809
94928
  }
94810
94929
  function quoteSystemdArg(value) {
@@ -94818,7 +94937,7 @@ function resolveCliPath() {
94818
94937
  if (!entry) {
94819
94938
  throw new Error("Unable to resolve current okx-a2a CLI path");
94820
94939
  }
94821
- return (0, import_node_path24.resolve)(entry);
94940
+ return (0, import_node_path25.resolve)(entry);
94822
94941
  }
94823
94942
  function buildSystemdUserService() {
94824
94943
  const taskHome2 = resolveTaskHome();
@@ -94953,10 +95072,10 @@ async function installAutostart() {
94953
95072
  }
94954
95073
  function isAutostartInstalled() {
94955
95074
  if (process.platform === "linux") {
94956
- return (0, import_node_fs19.existsSync)(resolveSystemdAutostartPaths().servicePath);
95075
+ return (0, import_node_fs20.existsSync)(resolveSystemdAutostartPaths().servicePath);
94957
95076
  }
94958
95077
  if (process.platform === "darwin") {
94959
- return (0, import_node_fs19.existsSync)(resolveLaunchdAutostartPaths().plistPath);
95078
+ return (0, import_node_fs20.existsSync)(resolveLaunchdAutostartPaths().plistPath);
94960
95079
  }
94961
95080
  if (process.platform === "win32") {
94962
95081
  return isWindowsAutostartInstalled();
@@ -94964,7 +95083,11 @@ function isAutostartInstalled() {
94964
95083
  return false;
94965
95084
  }
94966
95085
 
95086
+ // src/doctor-cli.ts
95087
+ init_daemon();
95088
+
94967
95089
  // src/daemon-ops.ts
95090
+ init_daemon();
94968
95091
  async function refreshAgentsAndWait(timeoutMs = 6e4) {
94969
95092
  const status = await getDaemonStatus();
94970
95093
  if (!status.running) {
@@ -95021,7 +95144,9 @@ async function dispatchRuntimeSwitchUserMessage(store, result) {
95021
95144
  // src/doctor-cli.ts
95022
95145
  init_session_store();
95023
95146
  init_update_cli();
95147
+ init_win_native_launcher();
95024
95148
  init_win_spawn();
95149
+ init_win_native_launcher();
95025
95150
  var DOCTOR_MIN_NODE_VERSION = "22.14.0";
95026
95151
  var DOCTOR_DAEMON_READY_TIMEOUT_MS = 2e4;
95027
95152
  var NODE_PACKAGE_SPEC = "@okxweb3/a2a-node";
@@ -95231,22 +95356,6 @@ var cliVersionChecker = {
95231
95356
  return `npm install completed; installed version could not be verified from npm metadata (was ${before}) \u2014 daemon will be restarted to be safe`;
95232
95357
  }
95233
95358
  };
95234
- function findWindowsNativeOkxA2aExe(pathValue, appData, userProfile, fileExists2 = import_node_fs21.existsSync) {
95235
- const dirs = pathValue.split(";").map((d) => d.trim()).filter(Boolean);
95236
- if (appData) {
95237
- dirs.push((0, import_node_path26.join)(appData, "npm"));
95238
- }
95239
- if (userProfile) {
95240
- dirs.push((0, import_node_path26.join)(userProfile, ".local", "bin"));
95241
- }
95242
- for (const dir of dirs) {
95243
- const candidate = (0, import_node_path26.join)(dir, "okx-a2a.exe");
95244
- if (fileExists2(candidate)) {
95245
- return candidate;
95246
- }
95247
- }
95248
- return null;
95249
- }
95250
95359
  var windowsNativeLauncherChecker = {
95251
95360
  id: "windows_native_launcher",
95252
95361
  title: "Windows native launcher (okx-a2a.exe)",
@@ -95283,27 +95392,13 @@ var windowsNativeLauncherChecker = {
95283
95392
  };
95284
95393
  },
95285
95394
  applyFix: async (ctx) => {
95286
- const targetDir = ctx.env.APPDATA ? (0, import_node_path26.join)(ctx.env.APPDATA, "npm") : (0, import_node_path26.join)(ctx.env.USERPROFILE ?? (0, import_node_os10.homedir)(), ".local", "bin");
95287
- const cliPath = resolveRunningCliPath();
95288
- const { installWindowsNativeLauncher: installWindowsNativeLauncher2 } = await Promise.resolve().then(() => (init_win_native_launcher(), win_native_launcher_exports));
95289
- const result = await installWindowsNativeLauncher2({ cliPath, targetDir });
95290
- return `built native launcher ${result.exePath} (SEA over ${result.nodeExe}, entry ${result.cliPath})`;
95395
+ const result = await ensureWindowsNativeLauncher({ env: ctx.env, platform: "win32" });
95396
+ if (!result) {
95397
+ throw new Error("native launcher fix is only applicable on Windows");
95398
+ }
95399
+ return result.installed ? `built native launcher ${result.exePath} (SEA over your node.exe)` : `native launcher already present at ${result.exePath}`;
95291
95400
  }
95292
95401
  };
95293
- function resolveRunningCliPath() {
95294
- const fromArgv = process.argv[1];
95295
- if (fromArgv && /(?:^|[\\/])cli\.js$/.test(fromArgv) && (0, import_node_fs21.existsSync)(fromArgv)) {
95296
- return fromArgv;
95297
- }
95298
- const beside = (0, import_node_path26.join)(__dirname, "cli.js");
95299
- if ((0, import_node_fs21.existsSync)(beside)) {
95300
- return beside;
95301
- }
95302
- if (fromArgv) {
95303
- return fromArgv;
95304
- }
95305
- throw new Error("could not resolve the running okx-a2a CLI path for the native launcher");
95306
- }
95307
95402
  var providerBindingChecker = {
95308
95403
  id: "provider_binding",
95309
95404
  title: "Default AI provider binding",
@@ -95407,7 +95502,14 @@ var providerCliChecker = {
95407
95502
  status: "fail",
95408
95503
  severity: "required",
95409
95504
  detail: `${provider} CLI at ${resolved} is not logged in (${auth.reason})`,
95410
- fix: {
95505
+ // Logging in needs a human (device/browser auth). In --non-interactive
95506
+ // mode never launch it — degrade to a manual instruction so unattended
95507
+ // callers (install scripts) cannot hang waiting on stdin.
95508
+ fix: ctx.nonInteractive ? {
95509
+ kind: "manual",
95510
+ description: "Log in with the command below, then re-run okx-a2a doctor.",
95511
+ command: loginCommand
95512
+ } : {
95411
95513
  kind: "auto",
95412
95514
  description: "--fix launches the interactive login flow (same as setup: device/browser auth, waits for completion). You can also log in yourself with the command below, then re-run okx-a2a doctor.",
95413
95515
  command: loginCommand
@@ -95446,6 +95548,11 @@ var providerCliChecker = {
95446
95548
  }
95447
95549
  const auth = provider === "codex" ? await checkCodexCliAuthStatus(resolved) : await checkClaudeCliAuthStatus(resolved);
95448
95550
  if (!auth.ok) {
95551
+ if (ctx.nonInteractive) {
95552
+ throw new Error(
95553
+ `${provider} CLI is installed but not logged in; non-interactive mode skips the login flow \u2014 log in yourself and re-run okx-a2a doctor`
95554
+ );
95555
+ }
95449
95556
  errorWithTimestamp(`[doctor] launching ${provider} CLI login (interactive; waiting for completion)`);
95450
95557
  const login = await runProviderLoginInteractive(provider, resolved);
95451
95558
  if (!login.ok) {
@@ -95469,13 +95576,14 @@ var gatewayPluginChecker = {
95469
95576
  return null;
95470
95577
  }
95471
95578
  const installed = await isGatewayPluginInstalled(ctx.target);
95579
+ const hermesPathSuffix = ctx.target === "hermes" ? ` (checked ${resolveHermesPluginYamlPath()})` : "";
95472
95580
  if (installed) {
95473
95581
  return {
95474
95582
  id: "gateway_plugin",
95475
95583
  title: "Gateway plugin installed",
95476
95584
  status: "pass",
95477
95585
  severity: "required",
95478
- detail: `${ctx.target} okx-a2a plugin is installed`
95586
+ detail: `${ctx.target} okx-a2a plugin is installed${hermesPathSuffix}`
95479
95587
  };
95480
95588
  }
95481
95589
  const hermesOnWindows = ctx.target === "hermes" && ctx.platform === "win32";
@@ -95484,7 +95592,7 @@ var gatewayPluginChecker = {
95484
95592
  title: "Gateway plugin installed",
95485
95593
  status: "fail",
95486
95594
  severity: "required",
95487
- detail: `${ctx.target} okx-a2a plugin is not installed`,
95595
+ detail: `${ctx.target} okx-a2a plugin is not installed${hermesPathSuffix}`,
95488
95596
  fix: hermesOnWindows ? {
95489
95597
  kind: "manual",
95490
95598
  description: "Hermes plugin installation requires bash and is not supported on Windows. Use WSL or run setup on macOS/Linux."
@@ -95513,13 +95621,14 @@ var gatewayConfigChecker = {
95513
95621
  return null;
95514
95622
  }
95515
95623
  const drift = ctx.target === "openclaw" ? await ensureOpenClawOkxA2aPluginConfig({ dryRun: true }) : await ensureHermesOkxA2aPluginConfig(void 0, { dryRun: true });
95624
+ const hermesPathSuffix = ctx.target === "hermes" ? ` (checked ${resolveHermesConfigPath()})` : "";
95516
95625
  if (!drift) {
95517
95626
  return {
95518
95627
  id: "gateway_config",
95519
95628
  title: "Gateway plugin config",
95520
95629
  status: "pass",
95521
95630
  severity: "required",
95522
- detail: `${ctx.target} okx-a2a plugin config is normalized`
95631
+ detail: `${ctx.target} okx-a2a plugin config is normalized${hermesPathSuffix}`
95523
95632
  };
95524
95633
  }
95525
95634
  return {
@@ -95527,7 +95636,7 @@ var gatewayConfigChecker = {
95527
95636
  title: "Gateway plugin config",
95528
95637
  status: "fail",
95529
95638
  severity: "required",
95530
- detail: `${ctx.target} okx-a2a plugin config needs normalization`,
95639
+ detail: `${ctx.target} okx-a2a plugin config needs normalization${hermesPathSuffix}`,
95531
95640
  fix: { kind: "auto", description: `Apply the ${ctx.target} config normalization in-process.` }
95532
95641
  };
95533
95642
  },
@@ -95775,8 +95884,9 @@ async function runDoctor(options = {}) {
95775
95884
  platform: options.platform ?? process.platform,
95776
95885
  env: options.env ?? process.env,
95777
95886
  target: options.target ?? resolveDoctorTarget(options.env ?? process.env),
95778
- cliVersion: options.cliVersion ?? (true ? "0.1.5" : "0.0.0"),
95887
+ cliVersion: options.cliVersion ?? (true ? "0.1.6" : "0.0.0"),
95779
95888
  fixMode: options.fix === true,
95889
+ nonInteractive: options.nonInteractive === true,
95780
95890
  packageChanged: false
95781
95891
  };
95782
95892
  const checkers = options.checkers ?? CHECKERS;
@@ -95923,6 +96033,7 @@ function formatDoctorReportForHumans(report) {
95923
96033
  async function handleDoctorCommand(args) {
95924
96034
  const json = args.includes("--json");
95925
96035
  const fix = args.includes("--fix");
96036
+ const nonInteractive = args.includes("--non-interactive");
95926
96037
  const targetIndex = args.indexOf("--target");
95927
96038
  const rawTarget = targetIndex >= 0 ? args[targetIndex + 1] : void 0;
95928
96039
  if (targetIndex >= 0 && (rawTarget === void 0 || rawTarget.startsWith("--"))) {
@@ -95946,7 +96057,7 @@ async function handleDoctorCommand(args) {
95946
96057
  };
95947
96058
  let report;
95948
96059
  try {
95949
- report = await runDoctor({ fix, ...rawTarget ? { target: rawTarget } : {} });
96060
+ report = await runDoctor({ fix, nonInteractive, ...rawTarget ? { target: rawTarget } : {} });
95950
96061
  } catch (error) {
95951
96062
  restoreStdout();
95952
96063
  const message = error instanceof Error ? error.message : String(error);
@@ -96052,12 +96163,14 @@ init_win_native_launcher();
96052
96163
  ensureDaemonReady,
96053
96164
  ensureDefaultAiProvider,
96054
96165
  ensureOpenClawOkxA2aPluginConfig,
96166
+ ensureWindowsNativeLauncher,
96055
96167
  extractAiSessionId,
96056
96168
  extractXmtpSentAtMs,
96057
96169
  findWindowsNativeOkxA2aExe,
96058
96170
  followFile,
96059
96171
  formatDoctorReportForHumans,
96060
96172
  getDaemonStatus,
96173
+ getHermesGatewayPluginStatus,
96061
96174
  handleDoctorCommand,
96062
96175
  handleXmtpSendCommand,
96063
96176
  hasAiRuntimeMarker,