@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.
- package/dist/cli.js +349 -256
- package/dist/index.js +878 -765
- 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.
|
|
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,
|
|
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,
|
|
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,
|
|
71801
|
-
const pluginDir = (0,
|
|
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,
|
|
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.
|
|
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,
|
|
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,
|
|
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
|
-
|
|
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()
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
|
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
|
-
|
|
72554
|
-
|
|
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
|
-
|
|
72557
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
|
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
|
-
|
|
93847
|
-
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
|
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,
|
|
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
|
|
94612
|
-
var
|
|
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
|
|
94615
|
-
var
|
|
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
|
|
94620
|
-
var
|
|
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
|
|
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,
|
|
94752
|
+
const autostartDir = (0, import_node_path24.join)(resolvedHome, "autostart");
|
|
94634
94753
|
return {
|
|
94635
94754
|
autostartDir,
|
|
94636
|
-
vbsPath: (0,
|
|
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,
|
|
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,
|
|
94832
|
+
return (0, import_node_path24.resolve)(entry);
|
|
94714
94833
|
}
|
|
94715
94834
|
function runSchtasks(operation, args) {
|
|
94716
|
-
const result = (0,
|
|
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,
|
|
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,
|
|
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)(
|
|
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,
|
|
94797
|
-
const serviceDir = (0,
|
|
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,
|
|
94919
|
+
servicePath: (0, import_node_path25.join)(serviceDir, SERVICE_NAME)
|
|
94801
94920
|
};
|
|
94802
94921
|
}
|
|
94803
|
-
function resolveLaunchdAutostartPaths(home = (0,
|
|
94804
|
-
const agentDir = (0,
|
|
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,
|
|
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,
|
|
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,
|
|
95075
|
+
return (0, import_node_fs20.existsSync)(resolveSystemdAutostartPaths().servicePath);
|
|
94957
95076
|
}
|
|
94958
95077
|
if (process.platform === "darwin") {
|
|
94959
|
-
return (0,
|
|
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
|
|
95287
|
-
|
|
95288
|
-
|
|
95289
|
-
|
|
95290
|
-
return `built native launcher ${result.exePath} (SEA over
|
|
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
|
-
|
|
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.
|
|
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,
|