@okxweb3/a2a-node 0.1.4 → 0.1.6-beta-c3024b2b0b-260706164140
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 +375 -266
- package/dist/index.js +902 -773
- 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, {
|
|
@@ -2228,11 +2742,25 @@ function switchProvider(options) {
|
|
|
2228
2742
|
readParentProcessCommand: options.readParentProcessCommand
|
|
2229
2743
|
});
|
|
2230
2744
|
if (runtime === "unknown") {
|
|
2745
|
+
const stored = options.store.getDefaultAiProvider();
|
|
2746
|
+
if (stored) {
|
|
2747
|
+
return {
|
|
2748
|
+
ok: true,
|
|
2749
|
+
runtime: "unknown",
|
|
2750
|
+
provider: stored,
|
|
2751
|
+
previousProvider: stored,
|
|
2752
|
+
changed: false,
|
|
2753
|
+
action: "kept_existing",
|
|
2754
|
+
userMessage: `No AI runtime detected for the current environment; keeping the existing default provider (${formatAiProviderDisplayName(stored)}).`
|
|
2755
|
+
};
|
|
2756
|
+
}
|
|
2231
2757
|
return {
|
|
2232
2758
|
ok: false,
|
|
2233
2759
|
runtime: "unknown",
|
|
2234
2760
|
reason: "unknown_runtime",
|
|
2235
|
-
|
|
2761
|
+
state: "blocked",
|
|
2762
|
+
message: "Could not determine the current AI provider.",
|
|
2763
|
+
userMessage: "Could not detect the current AI runtime and no default AI provider is configured. Run this from your AI environment (OpenClaw / Codex / Claude / Hermes), or set a provider manually: `okx-a2a ai-provider set --provider <codex|claude|hermes|openclaw>`."
|
|
2236
2764
|
};
|
|
2237
2765
|
}
|
|
2238
2766
|
const previousProvider = options.store.getDefaultAiProvider();
|
|
@@ -2244,6 +2772,7 @@ function switchProvider(options) {
|
|
|
2244
2772
|
provider: runtime,
|
|
2245
2773
|
previousProvider,
|
|
2246
2774
|
changed,
|
|
2775
|
+
action: "switched",
|
|
2247
2776
|
userMessage: changed ? `Switched to ${formatAiProviderDisplayName(runtime)}\uFF5CNew tasks will be handled here; unfinished tasks should be continued in their original session` : ""
|
|
2248
2777
|
};
|
|
2249
2778
|
}
|
|
@@ -70893,6 +71422,207 @@ var require_ws = __commonJS({
|
|
|
70893
71422
|
}
|
|
70894
71423
|
});
|
|
70895
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
|
+
|
|
70896
71626
|
// src/update-cli.ts
|
|
70897
71627
|
var update_cli_exports = {};
|
|
70898
71628
|
__export(update_cli_exports, {
|
|
@@ -70918,6 +71648,8 @@ __export(update_cli_exports, {
|
|
|
70918
71648
|
parseUpdateArgs: () => parseUpdateArgs,
|
|
70919
71649
|
printSetupUsage: () => printSetupUsage,
|
|
70920
71650
|
printUpdateUsage: () => printUpdateUsage,
|
|
71651
|
+
resolveHermesConfigPath: () => resolveHermesConfigPath,
|
|
71652
|
+
resolveHermesPluginYamlPath: () => resolveHermesPluginYamlPath,
|
|
70921
71653
|
runProviderLoginInteractive: () => runProviderLoginInteractive,
|
|
70922
71654
|
setRedirectCommandStdoutToStderr: () => setRedirectCommandStdoutToStderr
|
|
70923
71655
|
});
|
|
@@ -71131,6 +71863,7 @@ async function runSetup(options) {
|
|
|
71131
71863
|
if (nodeChange.nodeChanged && provider) {
|
|
71132
71864
|
await restartNodeDaemonAfterNodeSetup();
|
|
71133
71865
|
}
|
|
71866
|
+
await ensureWindowsNativeLauncherForSetup();
|
|
71134
71867
|
return {
|
|
71135
71868
|
ok: true,
|
|
71136
71869
|
state: "ready",
|
|
@@ -71164,6 +71897,7 @@ async function runSetup(options) {
|
|
|
71164
71897
|
if (changes.pluginChanged) {
|
|
71165
71898
|
await restartGatewayAfterSetup(resolvedTarget);
|
|
71166
71899
|
}
|
|
71900
|
+
await ensureWindowsNativeLauncherForSetup();
|
|
71167
71901
|
warnIfProviderMismatch(resolvedTarget);
|
|
71168
71902
|
return {
|
|
71169
71903
|
ok: true,
|
|
@@ -71610,7 +72344,7 @@ async function getCurrentNodeCliVersion() {
|
|
|
71610
72344
|
return await getGlobalNpmPackageVersion(UPDATE_PACKAGES.node) ?? getBundledNodeCliVersion();
|
|
71611
72345
|
}
|
|
71612
72346
|
function getBundledNodeCliVersion() {
|
|
71613
|
-
return true ? "0.1.
|
|
72347
|
+
return true ? "0.1.6-beta-c3024b2b0b-260706164140" : null;
|
|
71614
72348
|
}
|
|
71615
72349
|
function readConfiguredAiProvider() {
|
|
71616
72350
|
const explicit = process.env.OKX_A2A_AI_PROVIDER || process.env.OKX_AGENT_TASK_AI_CLI;
|
|
@@ -71641,10 +72375,29 @@ async function restartNodeDaemonAfterUpdate() {
|
|
|
71641
72375
|
}
|
|
71642
72376
|
async function installNode(release, label) {
|
|
71643
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
|
+
}
|
|
71644
72386
|
console.log(`[${label}] installing ${spec}`);
|
|
71645
72387
|
await runCommand("npm", ["install", "-g", spec]);
|
|
71646
72388
|
console.log(`[${label}] okx-a2a node CLI ${label === "setup" ? "setup" : "update"} done`);
|
|
71647
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
|
+
}
|
|
71648
72401
|
async function restartNodeDaemonAfterSetup(provider) {
|
|
71649
72402
|
console.log(`[setup] restarting okx-a2a daemon after node CLI setup with provider=${provider}`);
|
|
71650
72403
|
await runCommand("okx-a2a", ["daemon", "restart", "--provider", provider]);
|
|
@@ -71776,17 +72529,17 @@ async function updateHermes(release, options) {
|
|
|
71776
72529
|
assertNotRunningInsideGateway("hermes");
|
|
71777
72530
|
}
|
|
71778
72531
|
const spec = buildNpmPackageSpec("hermes", release);
|
|
71779
|
-
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-`));
|
|
71780
72533
|
try {
|
|
71781
72534
|
console.log(`[${label}] downloading ${spec}`);
|
|
71782
72535
|
const npmTarball = await npmPack(spec, workDir);
|
|
71783
|
-
const npmPackageDir = (0,
|
|
72536
|
+
const npmPackageDir = (0, import_node_path23.join)(workDir, "npm-package");
|
|
71784
72537
|
await runCommand("tar", ["-xzf", npmTarball, "-C", npmPackageDir], { ensureDir: npmPackageDir });
|
|
71785
|
-
const pluginTarball = await findHermesPluginTarball((0,
|
|
71786
|
-
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");
|
|
71787
72540
|
await runCommand("tar", ["-xzf", pluginTarball, "-C", pluginDir], { ensureDir: pluginDir });
|
|
71788
72541
|
const unpackedPluginDir = await findFirstDirectory(pluginDir);
|
|
71789
|
-
const installer = (0,
|
|
72542
|
+
const installer = (0, import_node_path23.join)(unpackedPluginDir, "scripts", "install-or-upgrade.sh");
|
|
71790
72543
|
console.log(`[${label}] running ${installer}`);
|
|
71791
72544
|
await runCommand("bash", [installer, ...options.restart ? ["--restart"] : []], { cwd: unpackedPluginDir });
|
|
71792
72545
|
await normalizeHermesOkxA2aPluginConfig();
|
|
@@ -71801,7 +72554,7 @@ async function updateHermes(release, options) {
|
|
|
71801
72554
|
}
|
|
71802
72555
|
}
|
|
71803
72556
|
async function installGatewayPluginForDoctor(target) {
|
|
71804
|
-
const release = isPrereleaseVersion("0.1.
|
|
72557
|
+
const release = isPrereleaseVersion("0.1.6-beta-c3024b2b0b-260706164140") ? "beta" : "latest";
|
|
71805
72558
|
const insideTargetGateway = detectGatewayInvocation() === target;
|
|
71806
72559
|
const options = {
|
|
71807
72560
|
restart: !insideTargetGateway,
|
|
@@ -71852,7 +72605,7 @@ async function ensureHermesOkxA2aPluginConfig(configFile = resolveHermesConfigPa
|
|
|
71852
72605
|
if (options.dryRun) {
|
|
71853
72606
|
return true;
|
|
71854
72607
|
}
|
|
71855
|
-
await (0, import_promises7.mkdir)((0,
|
|
72608
|
+
await (0, import_promises7.mkdir)((0, import_node_path23.resolve)(configFile, ".."), { recursive: true });
|
|
71856
72609
|
await (0, import_promises7.writeFile)(configFile, "plugins:\n enabled:\n - okx-a2a\n");
|
|
71857
72610
|
console.log(`[update] added Hermes plugins.enabled okx-a2a entry in ${configFile}`);
|
|
71858
72611
|
return true;
|
|
@@ -72092,7 +72845,7 @@ function findFirstEnabledListItem(lines, startIndex, enabledIndent) {
|
|
|
72092
72845
|
return null;
|
|
72093
72846
|
}
|
|
72094
72847
|
function resolveHermesConfigPath() {
|
|
72095
|
-
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");
|
|
72096
72849
|
}
|
|
72097
72850
|
function lineIndent(line) {
|
|
72098
72851
|
const match = line.match(/^\s*/);
|
|
@@ -72169,22 +72922,18 @@ async function assertGatewayPluginInstalled(target) {
|
|
|
72169
72922
|
`okx-a2a ${target} plugin is not installed. Run \`okx-a2a setup ${target}\` first; use \`okx-a2a update ${target}\` only for an existing installation.`
|
|
72170
72923
|
);
|
|
72171
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
|
+
}
|
|
72172
72928
|
async function isGatewayPluginInstalled(target) {
|
|
72173
72929
|
if (target === "openclaw") {
|
|
72174
72930
|
return (await getInstalledOpenClawPluginInfo()).installed;
|
|
72175
72931
|
}
|
|
72176
|
-
|
|
72177
|
-
return true;
|
|
72178
|
-
}
|
|
72179
|
-
return await isGlobalNpmPackageInstalled(UPDATE_PACKAGES.hermes);
|
|
72180
|
-
}
|
|
72181
|
-
async function isGlobalNpmPackageInstalled(packageName) {
|
|
72182
|
-
const result = await runCommandCaptureOptional("npm", ["list", "-g", packageName, "--depth=0"]);
|
|
72183
|
-
return result.ok && result.stdout.includes(packageName);
|
|
72932
|
+
return (0, import_node_fs17.existsSync)(resolveHermesPluginYamlPath());
|
|
72184
72933
|
}
|
|
72185
72934
|
async function getInstalledGatewayPluginVersion(target) {
|
|
72186
72935
|
if (target === "hermes") {
|
|
72187
|
-
return await getInstalledHermesPluginVersion()
|
|
72936
|
+
return await getInstalledHermesPluginVersion();
|
|
72188
72937
|
}
|
|
72189
72938
|
return (await getInstalledOpenClawPluginInfo()).version;
|
|
72190
72939
|
}
|
|
@@ -72267,7 +73016,7 @@ function parsePackageVersionFromText(output) {
|
|
|
72267
73016
|
return output.match(/@okxweb3\/a2a-openclaw@([0-9A-Za-z.+-]+)/)?.[1] ?? null;
|
|
72268
73017
|
}
|
|
72269
73018
|
async function getInstalledHermesPluginVersion() {
|
|
72270
|
-
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");
|
|
72271
73020
|
try {
|
|
72272
73021
|
const content3 = await (0, import_promises7.readFile)(pluginYaml, "utf8");
|
|
72273
73022
|
return parsePluginYamlVersion(content3);
|
|
@@ -72325,7 +73074,7 @@ async function npmPack(spec, destination) {
|
|
|
72325
73074
|
if (!tarballName) {
|
|
72326
73075
|
throw new Error(`Unable to detect npm pack tarball from output: ${output.trim()}`);
|
|
72327
73076
|
}
|
|
72328
|
-
return (0,
|
|
73077
|
+
return (0, import_node_path23.resolve)(destination, (0, import_node_path23.basename)(tarballName));
|
|
72329
73078
|
}
|
|
72330
73079
|
async function findHermesPluginTarball(distDir) {
|
|
72331
73080
|
const entries = await (0, import_promises7.readdir)(distDir);
|
|
@@ -72333,7 +73082,7 @@ async function findHermesPluginTarball(distDir) {
|
|
|
72333
73082
|
if (!tarball) {
|
|
72334
73083
|
throw new Error(`Hermes npm package did not contain dist/okx-a2a-hermes-plugin-*.tar.gz`);
|
|
72335
73084
|
}
|
|
72336
|
-
return (0,
|
|
73085
|
+
return (0, import_node_path23.join)(distDir, tarball);
|
|
72337
73086
|
}
|
|
72338
73087
|
async function findFirstDirectory(parent) {
|
|
72339
73088
|
const entries = await (0, import_promises7.readdir)(parent, { withFileTypes: true });
|
|
@@ -72341,7 +73090,7 @@ async function findFirstDirectory(parent) {
|
|
|
72341
73090
|
if (!dir) {
|
|
72342
73091
|
throw new Error(`No unpacked plugin directory found under ${parent}`);
|
|
72343
73092
|
}
|
|
72344
|
-
return (0,
|
|
73093
|
+
return (0, import_node_path23.join)(parent, dir.name);
|
|
72345
73094
|
}
|
|
72346
73095
|
function readOption(args, name2) {
|
|
72347
73096
|
const index2 = args.indexOf(name2);
|
|
@@ -72392,7 +73141,7 @@ async function runCommand(command, args, options = {}) {
|
|
|
72392
73141
|
await new Promise((resolvePromise, reject) => {
|
|
72393
73142
|
const invocation = buildExternalCommandInvocation(command, args);
|
|
72394
73143
|
const redirect = redirectCommandStdoutToStderr || options.redirectStdoutToStderr === true;
|
|
72395
|
-
const child = (0,
|
|
73144
|
+
const child = (0, import_node_child_process6.spawn)(invocation.command, invocation.args, {
|
|
72396
73145
|
cwd: options.cwd,
|
|
72397
73146
|
stdio: redirect ? [options.inheritStdin ? "inherit" : "ignore", "pipe", "pipe"] : "inherit",
|
|
72398
73147
|
windowsVerbatimArguments: invocation.windowsVerbatimArguments
|
|
@@ -72436,7 +73185,7 @@ async function runCommand(command, args, options = {}) {
|
|
|
72436
73185
|
async function runCommandCapture(command, args) {
|
|
72437
73186
|
return await new Promise((resolvePromise, reject) => {
|
|
72438
73187
|
const invocation = buildExternalCommandInvocation(command, args);
|
|
72439
|
-
const child = (0,
|
|
73188
|
+
const child = (0, import_node_child_process6.spawn)(invocation.command, invocation.args, {
|
|
72440
73189
|
stdio: ["ignore", "pipe", "pipe"],
|
|
72441
73190
|
windowsVerbatimArguments: invocation.windowsVerbatimArguments
|
|
72442
73191
|
});
|
|
@@ -72469,7 +73218,7 @@ ${stderr}`));
|
|
|
72469
73218
|
async function runCommandCaptureOptional(command, args) {
|
|
72470
73219
|
return await new Promise((resolvePromise) => {
|
|
72471
73220
|
const invocation = buildExternalCommandInvocation(command, args);
|
|
72472
|
-
const child = (0,
|
|
73221
|
+
const child = (0, import_node_child_process6.spawn)(invocation.command, invocation.args, {
|
|
72473
73222
|
stdio: ["ignore", "pipe", "ignore"],
|
|
72474
73223
|
windowsVerbatimArguments: invocation.windowsVerbatimArguments
|
|
72475
73224
|
});
|
|
@@ -72489,7 +73238,7 @@ async function runCommandCaptureOptional(command, args) {
|
|
|
72489
73238
|
async function runCommandCaptureStatus(command, args) {
|
|
72490
73239
|
return await new Promise((resolvePromise) => {
|
|
72491
73240
|
const invocation = buildExternalCommandInvocation(command, args);
|
|
72492
|
-
const child = (0,
|
|
73241
|
+
const child = (0, import_node_child_process6.spawn)(invocation.command, invocation.args, {
|
|
72493
73242
|
stdio: ["ignore", "pipe", "pipe"],
|
|
72494
73243
|
windowsVerbatimArguments: invocation.windowsVerbatimArguments
|
|
72495
73244
|
});
|
|
@@ -72531,15 +73280,15 @@ function buildExternalCommandInvocation(command, args, platform = process.platfo
|
|
|
72531
73280
|
function formatExternalCommand(command, args) {
|
|
72532
73281
|
return [command, ...args].join(" ");
|
|
72533
73282
|
}
|
|
72534
|
-
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;
|
|
72535
73284
|
var init_update_cli = __esm({
|
|
72536
73285
|
"src/update-cli.ts"() {
|
|
72537
73286
|
"use strict";
|
|
72538
|
-
|
|
72539
|
-
|
|
73287
|
+
import_node_child_process6 = require("node:child_process");
|
|
73288
|
+
import_node_fs17 = require("node:fs");
|
|
72540
73289
|
import_promises7 = require("node:fs/promises");
|
|
72541
|
-
|
|
72542
|
-
|
|
73290
|
+
import_node_os8 = require("node:os");
|
|
73291
|
+
import_node_path23 = require("node:path");
|
|
72543
73292
|
init_ai_command();
|
|
72544
73293
|
init_win_spawn();
|
|
72545
73294
|
init_ai_provider();
|
|
@@ -72570,160 +73319,6 @@ var init_update_cli = __esm({
|
|
|
72570
73319
|
}
|
|
72571
73320
|
});
|
|
72572
73321
|
|
|
72573
|
-
// src/win-native-launcher.ts
|
|
72574
|
-
var win_native_launcher_exports = {};
|
|
72575
|
-
__export(win_native_launcher_exports, {
|
|
72576
|
-
NATIVE_LAUNCHER_EXE_NAME: () => NATIVE_LAUNCHER_EXE_NAME,
|
|
72577
|
-
buildLauncherEntryJs: () => buildLauncherEntryJs,
|
|
72578
|
-
buildSeaConfig: () => buildSeaConfig,
|
|
72579
|
-
installWindowsNativeLauncher: () => installWindowsNativeLauncher
|
|
72580
|
-
});
|
|
72581
|
-
function isPostjectRunnable() {
|
|
72582
|
-
try {
|
|
72583
|
-
const probe = spawnSyncCompat(POSTJECT_BIN, ["--help"], {
|
|
72584
|
-
stdio: "ignore",
|
|
72585
|
-
windowsHide: true,
|
|
72586
|
-
timeout: 3e4
|
|
72587
|
-
});
|
|
72588
|
-
return probe.status === 0;
|
|
72589
|
-
} catch {
|
|
72590
|
-
return false;
|
|
72591
|
-
}
|
|
72592
|
-
}
|
|
72593
|
-
function resolvePostjectCommand() {
|
|
72594
|
-
try {
|
|
72595
|
-
const cliPath = (0, import_node_module.createRequire)(__filename).resolve("postject/dist/cli.js");
|
|
72596
|
-
if ((0, import_node_fs20.existsSync)(cliPath)) {
|
|
72597
|
-
return { command: process.execPath, prefixArgs: [cliPath] };
|
|
72598
|
-
}
|
|
72599
|
-
} catch {
|
|
72600
|
-
}
|
|
72601
|
-
if (!isPostjectRunnable()) {
|
|
72602
|
-
logWinCompat(`${WIN_COMPAT_LOG_PREFIX} native launcher: installing ${POSTJECT_SPEC} globally`);
|
|
72603
|
-
const install = spawnSyncCompat("npm", [
|
|
72604
|
-
"install",
|
|
72605
|
-
"-g",
|
|
72606
|
-
POSTJECT_SPEC,
|
|
72607
|
-
"--no-audit",
|
|
72608
|
-
"--no-fund",
|
|
72609
|
-
"--loglevel=error"
|
|
72610
|
-
], { encoding: "utf8", windowsHide: true, timeout: 18e4 });
|
|
72611
|
-
if (install.status !== 0 || !isPostjectRunnable()) {
|
|
72612
|
-
throw new Error(
|
|
72613
|
-
`failed to install ${POSTJECT_SPEC} (needed to build okx-a2a.exe): ${String(install.stderr || install.error?.message || "unknown error").slice(0, 300)}`
|
|
72614
|
-
);
|
|
72615
|
-
}
|
|
72616
|
-
}
|
|
72617
|
-
return { command: POSTJECT_BIN, prefixArgs: [] };
|
|
72618
|
-
}
|
|
72619
|
-
function injectSeaBlob(exePath, blobPath, isMac) {
|
|
72620
|
-
const { command, prefixArgs: prefixArgs2 } = resolvePostjectCommand();
|
|
72621
|
-
const args = [
|
|
72622
|
-
...prefixArgs2,
|
|
72623
|
-
exePath,
|
|
72624
|
-
"NODE_SEA_BLOB",
|
|
72625
|
-
blobPath,
|
|
72626
|
-
"--sentinel-fuse",
|
|
72627
|
-
SEA_SENTINEL_FUSE,
|
|
72628
|
-
"--overwrite"
|
|
72629
|
-
];
|
|
72630
|
-
if (isMac) {
|
|
72631
|
-
args.push("--macho-segment-name", "NODE_SEA");
|
|
72632
|
-
}
|
|
72633
|
-
const result = spawnSyncCompat(command, args, {
|
|
72634
|
-
encoding: "utf8",
|
|
72635
|
-
windowsHide: true,
|
|
72636
|
-
timeout: 12e4
|
|
72637
|
-
});
|
|
72638
|
-
if (result.status !== 0) {
|
|
72639
|
-
throw new Error(
|
|
72640
|
-
`postject injection failed: ${String(result.stderr || result.error?.message || `exit ${result.status}`).slice(0, 300)}`
|
|
72641
|
-
);
|
|
72642
|
-
}
|
|
72643
|
-
}
|
|
72644
|
-
function buildLauncherEntryJs(cliPath) {
|
|
72645
|
-
const target = JSON.stringify(cliPath);
|
|
72646
|
-
return [
|
|
72647
|
-
'const { createRequire } = require("node:module");',
|
|
72648
|
-
`const nodeRequire = createRequire(${target});`,
|
|
72649
|
-
`nodeRequire(${target});`,
|
|
72650
|
-
""
|
|
72651
|
-
].join("\n");
|
|
72652
|
-
}
|
|
72653
|
-
function buildSeaConfig(entryPath, blobPath) {
|
|
72654
|
-
return `${JSON.stringify(
|
|
72655
|
-
{
|
|
72656
|
-
main: entryPath,
|
|
72657
|
-
output: blobPath,
|
|
72658
|
-
disableExperimentalSEAWarning: true
|
|
72659
|
-
},
|
|
72660
|
-
null,
|
|
72661
|
-
2
|
|
72662
|
-
)}
|
|
72663
|
-
`;
|
|
72664
|
-
}
|
|
72665
|
-
async function installWindowsNativeLauncher(options) {
|
|
72666
|
-
const nodeExe = options.nodeExe ?? process.execPath;
|
|
72667
|
-
if (!(0, import_node_fs20.existsSync)(options.cliPath)) {
|
|
72668
|
-
throw new Error(`cannot build okx-a2a.exe: CLI entry not found at ${options.cliPath}`);
|
|
72669
|
-
}
|
|
72670
|
-
if (!(0, import_node_fs20.existsSync)(nodeExe)) {
|
|
72671
|
-
throw new Error(`cannot build okx-a2a.exe: node executable not found at ${nodeExe}`);
|
|
72672
|
-
}
|
|
72673
|
-
const exePath = (0, import_node_path25.join)(options.targetDir, NATIVE_LAUNCHER_EXE_NAME);
|
|
72674
|
-
(0, import_node_fs20.mkdirSync)(options.targetDir, { recursive: true });
|
|
72675
|
-
const work = (0, import_node_fs20.mkdtempSync)((0, import_node_path25.join)((0, import_node_os9.tmpdir)(), "okx-a2a-sea-"));
|
|
72676
|
-
try {
|
|
72677
|
-
const entryPath = (0, import_node_path25.join)(work, "launcher-entry.js");
|
|
72678
|
-
const blobPath = (0, import_node_path25.join)(work, "okx-a2a.blob");
|
|
72679
|
-
const configPath = (0, import_node_path25.join)(work, "sea-config.json");
|
|
72680
|
-
(0, import_node_fs20.writeFileSync)(entryPath, buildLauncherEntryJs(options.cliPath), "utf8");
|
|
72681
|
-
(0, import_node_fs20.writeFileSync)(configPath, buildSeaConfig(entryPath, blobPath), "utf8");
|
|
72682
|
-
(0, import_node_child_process8.execFileSync)(nodeExe, ["--experimental-sea-config", configPath], {
|
|
72683
|
-
stdio: "ignore",
|
|
72684
|
-
windowsHide: true
|
|
72685
|
-
});
|
|
72686
|
-
(0, import_node_fs20.copyFileSync)(nodeExe, exePath);
|
|
72687
|
-
const isMac = process.platform === "darwin";
|
|
72688
|
-
if (isMac) {
|
|
72689
|
-
try {
|
|
72690
|
-
(0, import_node_child_process8.execFileSync)("codesign", ["--remove-signature", exePath], { stdio: "ignore" });
|
|
72691
|
-
} catch {
|
|
72692
|
-
}
|
|
72693
|
-
}
|
|
72694
|
-
injectSeaBlob(exePath, blobPath, isMac);
|
|
72695
|
-
if (isMac) {
|
|
72696
|
-
try {
|
|
72697
|
-
(0, import_node_child_process8.execFileSync)("codesign", ["--sign", "-", exePath], { stdio: "ignore" });
|
|
72698
|
-
} catch {
|
|
72699
|
-
}
|
|
72700
|
-
}
|
|
72701
|
-
logWinCompat(
|
|
72702
|
-
`${WIN_COMPAT_LOG_PREFIX} native launcher: built ${exePath} from node=${nodeExe} cli=${options.cliPath}`
|
|
72703
|
-
);
|
|
72704
|
-
return { exePath, cliPath: options.cliPath, nodeExe };
|
|
72705
|
-
} finally {
|
|
72706
|
-
(0, import_node_fs20.rmSync)(work, { recursive: true, force: true });
|
|
72707
|
-
}
|
|
72708
|
-
}
|
|
72709
|
-
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;
|
|
72710
|
-
var init_win_native_launcher = __esm({
|
|
72711
|
-
"src/win-native-launcher.ts"() {
|
|
72712
|
-
"use strict";
|
|
72713
|
-
import_node_child_process8 = require("node:child_process");
|
|
72714
|
-
import_node_fs20 = require("node:fs");
|
|
72715
|
-
import_node_module = require("node:module");
|
|
72716
|
-
import_node_os9 = require("node:os");
|
|
72717
|
-
import_node_path25 = require("node:path");
|
|
72718
|
-
init_win_compat();
|
|
72719
|
-
init_win_spawn();
|
|
72720
|
-
SEA_SENTINEL_FUSE = "NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2";
|
|
72721
|
-
NATIVE_LAUNCHER_EXE_NAME = "okx-a2a.exe";
|
|
72722
|
-
POSTJECT_SPEC = "postject@1.0.0-alpha.6";
|
|
72723
|
-
POSTJECT_BIN = "postject";
|
|
72724
|
-
}
|
|
72725
|
-
});
|
|
72726
|
-
|
|
72727
73322
|
// src/index.ts
|
|
72728
73323
|
var index_exports = {};
|
|
72729
73324
|
__export(index_exports, {
|
|
@@ -72798,12 +73393,14 @@ __export(index_exports, {
|
|
|
72798
73393
|
ensureDaemonReady: () => ensureDaemonReady,
|
|
72799
73394
|
ensureDefaultAiProvider: () => ensureDefaultAiProvider,
|
|
72800
73395
|
ensureOpenClawOkxA2aPluginConfig: () => ensureOpenClawOkxA2aPluginConfig,
|
|
73396
|
+
ensureWindowsNativeLauncher: () => ensureWindowsNativeLauncher,
|
|
72801
73397
|
extractAiSessionId: () => extractAiSessionId,
|
|
72802
73398
|
extractXmtpSentAtMs: () => extractXmtpSentAtMs2,
|
|
72803
73399
|
findWindowsNativeOkxA2aExe: () => findWindowsNativeOkxA2aExe,
|
|
72804
73400
|
followFile: () => followFile,
|
|
72805
73401
|
formatDoctorReportForHumans: () => formatDoctorReportForHumans,
|
|
72806
73402
|
getDaemonStatus: () => getDaemonStatus,
|
|
73403
|
+
getHermesGatewayPluginStatus: () => getHermesGatewayPluginStatus,
|
|
72807
73404
|
handleDoctorCommand: () => handleDoctorCommand,
|
|
72808
73405
|
handleXmtpSendCommand: () => handleXmtpSendCommand,
|
|
72809
73406
|
hasAiRuntimeMarker: () => hasAiRuntimeMarker,
|
|
@@ -72882,502 +73479,7 @@ __export(index_exports, {
|
|
|
72882
73479
|
writeAiPermissionPresetToConfig: () => writeAiPermissionPresetToConfig
|
|
72883
73480
|
});
|
|
72884
73481
|
module.exports = __toCommonJS(index_exports);
|
|
72885
|
-
|
|
72886
|
-
// src/daemon.ts
|
|
72887
|
-
var import_node_fs3 = require("node:fs");
|
|
72888
|
-
var import_promises2 = require("node:fs/promises");
|
|
72889
|
-
var import_node_child_process = require("node:child_process");
|
|
72890
|
-
var import_node_path5 = require("node:path");
|
|
72891
|
-
init_paths();
|
|
72892
|
-
init_session_store();
|
|
72893
|
-
|
|
72894
|
-
// src/daemon-lock.ts
|
|
72895
|
-
var import_promises = require("node:fs/promises");
|
|
72896
|
-
var import_node_path4 = require("node:path");
|
|
72897
|
-
init_paths();
|
|
72898
|
-
init_a2a_paths();
|
|
72899
|
-
var OWNER_FILE = "owner.json";
|
|
72900
|
-
var EMPTY_LOCK_STALE_MS = 1e4;
|
|
72901
|
-
var DAEMON_CAPABILITY_AI_DISPATCH = "ai-dispatch";
|
|
72902
|
-
var DAEMON_CAPABILITIES = [
|
|
72903
|
-
DAEMON_CAPABILITY_AI_DISPATCH
|
|
72904
|
-
];
|
|
72905
|
-
function isProcessAlive(pid) {
|
|
72906
|
-
try {
|
|
72907
|
-
process.kill(pid, 0);
|
|
72908
|
-
return true;
|
|
72909
|
-
} catch (err2) {
|
|
72910
|
-
return err2.code === "EPERM";
|
|
72911
|
-
}
|
|
72912
|
-
}
|
|
72913
|
-
function ownerPath(lockPath) {
|
|
72914
|
-
return (0, import_node_path4.join)(lockPath, OWNER_FILE);
|
|
72915
|
-
}
|
|
72916
|
-
async function readDaemonLock(lockPath) {
|
|
72917
|
-
let metadata = null;
|
|
72918
|
-
try {
|
|
72919
|
-
const raw = await (0, import_promises.readFile)(ownerPath(lockPath), "utf8");
|
|
72920
|
-
metadata = JSON.parse(raw);
|
|
72921
|
-
} catch (err2) {
|
|
72922
|
-
const code2 = err2.code;
|
|
72923
|
-
if (code2 === "ENOENT") {
|
|
72924
|
-
try {
|
|
72925
|
-
const info = await (0, import_promises.stat)(lockPath);
|
|
72926
|
-
const stale = Date.now() - info.mtimeMs > EMPTY_LOCK_STALE_MS;
|
|
72927
|
-
return { metadata: null, running: !stale, stale, path: lockPath };
|
|
72928
|
-
} catch (statErr) {
|
|
72929
|
-
const statCode = statErr.code;
|
|
72930
|
-
if (statCode === "ENOENT") {
|
|
72931
|
-
return { metadata: null, running: false, stale: false, path: lockPath };
|
|
72932
|
-
}
|
|
72933
|
-
throw statErr;
|
|
72934
|
-
}
|
|
72935
|
-
}
|
|
72936
|
-
if (err2 instanceof SyntaxError) {
|
|
72937
|
-
return { metadata: null, running: false, stale: true, path: lockPath };
|
|
72938
|
-
}
|
|
72939
|
-
throw err2;
|
|
72940
|
-
}
|
|
72941
|
-
const running = Number.isInteger(metadata.pid) && metadata.pid > 0 && isProcessAlive(metadata.pid);
|
|
72942
|
-
return { metadata, running, stale: !running, path: lockPath };
|
|
72943
|
-
}
|
|
72944
|
-
async function markDaemonReady(lockPath) {
|
|
72945
|
-
const current = await readDaemonLock(lockPath);
|
|
72946
|
-
const metadata = current.metadata;
|
|
72947
|
-
if (!metadata || metadata.pid !== process.pid) {
|
|
72948
|
-
return;
|
|
72949
|
-
}
|
|
72950
|
-
await (0, import_promises.writeFile)(ownerPath(lockPath), `${JSON.stringify({
|
|
72951
|
-
...metadata,
|
|
72952
|
-
ready: true,
|
|
72953
|
-
readyAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
72954
|
-
}, null, 2)}
|
|
72955
|
-
`, "utf8");
|
|
72956
|
-
}
|
|
72957
|
-
async function removeLock(lockPath) {
|
|
72958
|
-
await (0, import_promises.rm)(lockPath, { recursive: true, force: true });
|
|
72959
|
-
}
|
|
72960
|
-
async function acquireDaemonLock(paths, entry) {
|
|
72961
|
-
const metadata = {
|
|
72962
|
-
pid: process.pid,
|
|
72963
|
-
startedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
72964
|
-
cwd: process.cwd(),
|
|
72965
|
-
entry,
|
|
72966
|
-
homeDir: paths.homeDir,
|
|
72967
|
-
capabilities: DAEMON_CAPABILITIES,
|
|
72968
|
-
ready: false
|
|
72969
|
-
};
|
|
72970
|
-
ensureTaskDir(paths.runDir);
|
|
72971
|
-
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
72972
|
-
try {
|
|
72973
|
-
await (0, import_promises.mkdir)(paths.daemonLockPath, { mode: A2A_TASK_DIR_MODE });
|
|
72974
|
-
await chmodBestEffort(paths.daemonLockPath, A2A_TASK_DIR_MODE);
|
|
72975
|
-
await (0, import_promises.writeFile)(ownerPath(paths.daemonLockPath), `${JSON.stringify(metadata, null, 2)}
|
|
72976
|
-
`, "utf8");
|
|
72977
|
-
return {
|
|
72978
|
-
metadata,
|
|
72979
|
-
release: async () => {
|
|
72980
|
-
const current = await readDaemonLock(paths.daemonLockPath);
|
|
72981
|
-
if (current.metadata?.pid === process.pid) {
|
|
72982
|
-
await removeLock(paths.daemonLockPath);
|
|
72983
|
-
}
|
|
72984
|
-
}
|
|
72985
|
-
};
|
|
72986
|
-
} catch (err2) {
|
|
72987
|
-
const code2 = err2.code;
|
|
72988
|
-
if (code2 !== "EEXIST") {
|
|
72989
|
-
throw err2;
|
|
72990
|
-
}
|
|
72991
|
-
const current = await readDaemonLock(paths.daemonLockPath);
|
|
72992
|
-
if (current.running) {
|
|
72993
|
-
return null;
|
|
72994
|
-
}
|
|
72995
|
-
if (!current.stale) {
|
|
72996
|
-
return null;
|
|
72997
|
-
}
|
|
72998
|
-
await removeLock(paths.daemonLockPath);
|
|
72999
|
-
}
|
|
73000
|
-
}
|
|
73001
|
-
return null;
|
|
73002
|
-
}
|
|
73003
|
-
async function chmodBestEffort(path, mode) {
|
|
73004
|
-
try {
|
|
73005
|
-
await (0, import_promises.chmod)(path, mode);
|
|
73006
|
-
} catch (err2) {
|
|
73007
|
-
const code2 = err2.code;
|
|
73008
|
-
if (code2 !== "EPERM" && code2 !== "EACCES") {
|
|
73009
|
-
throw err2;
|
|
73010
|
-
}
|
|
73011
|
-
}
|
|
73012
|
-
}
|
|
73013
|
-
|
|
73014
|
-
// src/daemon.ts
|
|
73015
|
-
var STOP_GRACE_MS = 5e3;
|
|
73016
|
-
var FORCE_KILL_GRACE_MS = 5e3;
|
|
73017
|
-
var START_EXIT_CHECK_MS = 750;
|
|
73018
|
-
var DEFAULT_READY_TIMEOUT_MS = 12e4;
|
|
73019
|
-
var READY_POLL_MS = 250;
|
|
73020
|
-
var DAEMON_READY_TIMEOUT_ENV = "OKX_A2A_DAEMON_READY_TIMEOUT_MS";
|
|
73021
|
-
async function readPid(pidPath) {
|
|
73022
|
-
try {
|
|
73023
|
-
const raw = await (0, import_promises2.readFile)(pidPath, "utf8");
|
|
73024
|
-
const pid = Number.parseInt(raw.trim(), 10);
|
|
73025
|
-
return Number.isInteger(pid) && pid > 0 ? pid : null;
|
|
73026
|
-
} catch (err2) {
|
|
73027
|
-
const code2 = err2.code;
|
|
73028
|
-
if (code2 === "ENOENT") {
|
|
73029
|
-
return null;
|
|
73030
|
-
}
|
|
73031
|
-
throw err2;
|
|
73032
|
-
}
|
|
73033
|
-
}
|
|
73034
|
-
async function removePid(pidPath) {
|
|
73035
|
-
try {
|
|
73036
|
-
await (0, import_promises2.unlink)(pidPath);
|
|
73037
|
-
} catch (err2) {
|
|
73038
|
-
const code2 = err2.code;
|
|
73039
|
-
if (code2 !== "ENOENT") {
|
|
73040
|
-
throw err2;
|
|
73041
|
-
}
|
|
73042
|
-
}
|
|
73043
|
-
}
|
|
73044
|
-
async function ensureDaemonDirs(homeDir) {
|
|
73045
|
-
const paths = resolveTaskPaths(homeDir);
|
|
73046
|
-
ensureTaskDir(paths.jobsDir);
|
|
73047
|
-
ensureTaskDir(paths.runDir);
|
|
73048
|
-
ensureTaskDir(paths.logsDir);
|
|
73049
|
-
ensureTaskDir(paths.commandsDir);
|
|
73050
|
-
ensureTaskDir(paths.downloadsDir);
|
|
73051
|
-
ensureTaskDir(paths.xmtpDir);
|
|
73052
|
-
ensureTaskDir(paths.sqliteDir);
|
|
73053
|
-
return paths;
|
|
73054
|
-
}
|
|
73055
|
-
async function ensureAiWorkspace(paths) {
|
|
73056
|
-
const aiWorkingDir = paths.workspaceDir;
|
|
73057
|
-
await (0, import_promises2.rm)(aiWorkingDir, { recursive: true, force: true });
|
|
73058
|
-
ensureTaskDir(aiWorkingDir);
|
|
73059
|
-
return aiWorkingDir;
|
|
73060
|
-
}
|
|
73061
|
-
async function waitForImmediateExit(child, timeoutMs) {
|
|
73062
|
-
return await new Promise((resolve6) => {
|
|
73063
|
-
let timer;
|
|
73064
|
-
const onExit = () => {
|
|
73065
|
-
clearTimeout(timer);
|
|
73066
|
-
resolve6(true);
|
|
73067
|
-
};
|
|
73068
|
-
timer = setTimeout(() => {
|
|
73069
|
-
child.off("exit", onExit);
|
|
73070
|
-
resolve6(false);
|
|
73071
|
-
}, timeoutMs);
|
|
73072
|
-
child.once("exit", onExit);
|
|
73073
|
-
});
|
|
73074
|
-
}
|
|
73075
|
-
async function getDaemonStatus(homeDir) {
|
|
73076
|
-
const paths = resolveTaskPaths(homeDir);
|
|
73077
|
-
const pid = await readPid(paths.pidPath);
|
|
73078
|
-
const lock = await readDaemonLock(paths.daemonLockPath);
|
|
73079
|
-
const lockPid = lock.metadata?.pid ?? null;
|
|
73080
|
-
const lockReadyStateKnown = !!lock.metadata && (typeof lock.metadata.ready === "boolean" || typeof lock.metadata.readyAt === "string");
|
|
73081
|
-
const lockReady = lockReadyStateKnown ? lock.metadata?.ready === true || typeof lock.metadata?.readyAt === "string" : true;
|
|
73082
|
-
if (lock.running) {
|
|
73083
|
-
return {
|
|
73084
|
-
running: true,
|
|
73085
|
-
pid: lockPid ?? pid,
|
|
73086
|
-
stale: false,
|
|
73087
|
-
capabilities: lock.metadata?.capabilities ?? [],
|
|
73088
|
-
ready: lockReady,
|
|
73089
|
-
readyAt: lock.metadata?.readyAt ?? null,
|
|
73090
|
-
readyStateKnown: lockReadyStateKnown,
|
|
73091
|
-
pidPath: paths.pidPath,
|
|
73092
|
-
lockPath: paths.daemonLockPath,
|
|
73093
|
-
lockPid,
|
|
73094
|
-
lockStale: false
|
|
73095
|
-
};
|
|
73096
|
-
}
|
|
73097
|
-
if (!pid) {
|
|
73098
|
-
return {
|
|
73099
|
-
running: false,
|
|
73100
|
-
pid: null,
|
|
73101
|
-
stale: lock.stale,
|
|
73102
|
-
capabilities: [],
|
|
73103
|
-
ready: false,
|
|
73104
|
-
readyAt: null,
|
|
73105
|
-
readyStateKnown: false,
|
|
73106
|
-
pidPath: paths.pidPath,
|
|
73107
|
-
lockPath: paths.daemonLockPath,
|
|
73108
|
-
lockPid,
|
|
73109
|
-
lockStale: lock.stale
|
|
73110
|
-
};
|
|
73111
|
-
}
|
|
73112
|
-
const running = isProcessAlive(pid);
|
|
73113
|
-
return {
|
|
73114
|
-
running,
|
|
73115
|
-
pid,
|
|
73116
|
-
stale: !running || lock.stale,
|
|
73117
|
-
capabilities: running ? lock.metadata?.capabilities ?? [] : [],
|
|
73118
|
-
ready: running && !lockReadyStateKnown ? true : running && lockReady,
|
|
73119
|
-
readyAt: running ? lock.metadata?.readyAt ?? null : null,
|
|
73120
|
-
readyStateKnown: running && lockReadyStateKnown,
|
|
73121
|
-
pidPath: paths.pidPath,
|
|
73122
|
-
lockPath: paths.daemonLockPath,
|
|
73123
|
-
lockPid,
|
|
73124
|
-
lockStale: lock.stale
|
|
73125
|
-
};
|
|
73126
|
-
}
|
|
73127
|
-
async function startDaemon(homeDir) {
|
|
73128
|
-
const paths = await ensureDaemonDirs(homeDir);
|
|
73129
|
-
const aiWorkingDir = await ensureAiWorkspace(paths);
|
|
73130
|
-
const current = await getDaemonStatus(homeDir);
|
|
73131
|
-
if (current.running) {
|
|
73132
|
-
return {
|
|
73133
|
-
...current,
|
|
73134
|
-
started: false,
|
|
73135
|
-
logPath: paths.listenerLogPath
|
|
73136
|
-
};
|
|
73137
|
-
}
|
|
73138
|
-
if (current.stale) {
|
|
73139
|
-
await removePid(paths.pidPath);
|
|
73140
|
-
}
|
|
73141
|
-
const store = new SessionStore({ homeDir });
|
|
73142
|
-
try {
|
|
73143
|
-
store.setSetting("ai_working_dir", aiWorkingDir);
|
|
73144
|
-
store.resetGlobalSession(SYSTEM_NOTIFICATION_SESSION_KEY);
|
|
73145
|
-
} finally {
|
|
73146
|
-
store.close();
|
|
73147
|
-
}
|
|
73148
|
-
const logFd = (0, import_node_fs3.openSync)(paths.listenerLogPath, "a");
|
|
73149
|
-
const entry = process.env.OKX_AGENT_TASK_CLI_PATH || (0, import_node_path5.join)(__dirname, "cli.js");
|
|
73150
|
-
const daemonCwd = (0, import_node_path5.join)(__dirname, "..");
|
|
73151
|
-
const child = (0, import_node_child_process.spawn)(process.execPath, [entry, "run"], {
|
|
73152
|
-
cwd: daemonCwd,
|
|
73153
|
-
detached: true,
|
|
73154
|
-
// win32: keep the detached daemon from flashing/holding a console window.
|
|
73155
|
-
// Ignored on every non-win32 platform.
|
|
73156
|
-
windowsHide: true,
|
|
73157
|
-
env: {
|
|
73158
|
-
...process.env,
|
|
73159
|
-
OKX_AGENT_TASK_HOME: paths.homeDir,
|
|
73160
|
-
OKX_AGENT_TASK_DAEMON: "1",
|
|
73161
|
-
OKX_A2A_AI_CWD: aiWorkingDir,
|
|
73162
|
-
OKX_AGENT_TASK_AI_CWD: aiWorkingDir
|
|
73163
|
-
},
|
|
73164
|
-
stdio: ["ignore", logFd, logFd]
|
|
73165
|
-
});
|
|
73166
|
-
(0, import_node_fs3.closeSync)(logFd);
|
|
73167
|
-
child.unref();
|
|
73168
|
-
await (0, import_promises2.writeFile)(paths.pidPath, `${child.pid ?? ""}
|
|
73169
|
-
`, "utf8");
|
|
73170
|
-
if (await waitForImmediateExit(child, START_EXIT_CHECK_MS)) {
|
|
73171
|
-
const status = await getDaemonStatus(homeDir);
|
|
73172
|
-
if (status.running && status.lockPid) {
|
|
73173
|
-
await (0, import_promises2.writeFile)(paths.pidPath, `${status.lockPid}
|
|
73174
|
-
`, "utf8");
|
|
73175
|
-
} else {
|
|
73176
|
-
await removePid(paths.pidPath);
|
|
73177
|
-
}
|
|
73178
|
-
return {
|
|
73179
|
-
...status,
|
|
73180
|
-
started: false,
|
|
73181
|
-
logPath: paths.listenerLogPath
|
|
73182
|
-
};
|
|
73183
|
-
}
|
|
73184
|
-
return {
|
|
73185
|
-
running: true,
|
|
73186
|
-
pid: child.pid ?? null,
|
|
73187
|
-
stale: false,
|
|
73188
|
-
capabilities: DAEMON_CAPABILITIES,
|
|
73189
|
-
ready: false,
|
|
73190
|
-
readyAt: null,
|
|
73191
|
-
readyStateKnown: true,
|
|
73192
|
-
pidPath: paths.pidPath,
|
|
73193
|
-
lockPath: paths.daemonLockPath,
|
|
73194
|
-
lockPid: child.pid ?? null,
|
|
73195
|
-
lockStale: false,
|
|
73196
|
-
started: true,
|
|
73197
|
-
logPath: paths.listenerLogPath
|
|
73198
|
-
};
|
|
73199
|
-
}
|
|
73200
|
-
async function waitForExit(pid, timeoutMs) {
|
|
73201
|
-
const deadline = Date.now() + timeoutMs;
|
|
73202
|
-
while (Date.now() < deadline) {
|
|
73203
|
-
if (!isProcessAlive(pid)) {
|
|
73204
|
-
return true;
|
|
73205
|
-
}
|
|
73206
|
-
await new Promise((resolve6) => setTimeout(resolve6, 100));
|
|
73207
|
-
}
|
|
73208
|
-
return !isProcessAlive(pid);
|
|
73209
|
-
}
|
|
73210
|
-
function signalProcess(pid, signal) {
|
|
73211
|
-
try {
|
|
73212
|
-
process.kill(pid, signal);
|
|
73213
|
-
return true;
|
|
73214
|
-
} catch (err2) {
|
|
73215
|
-
const code2 = err2.code;
|
|
73216
|
-
if (code2 === "ESRCH") {
|
|
73217
|
-
return false;
|
|
73218
|
-
}
|
|
73219
|
-
throw err2;
|
|
73220
|
-
}
|
|
73221
|
-
}
|
|
73222
|
-
async function stopDaemon(homeDir) {
|
|
73223
|
-
const paths = resolveTaskPaths(homeDir);
|
|
73224
|
-
const current = await getDaemonStatus(homeDir);
|
|
73225
|
-
if (!current.pid) {
|
|
73226
|
-
return { ...current, stopped: false };
|
|
73227
|
-
}
|
|
73228
|
-
if (!current.running) {
|
|
73229
|
-
await removePid(paths.pidPath);
|
|
73230
|
-
return {
|
|
73231
|
-
running: false,
|
|
73232
|
-
pid: current.pid,
|
|
73233
|
-
stale: false,
|
|
73234
|
-
capabilities: [],
|
|
73235
|
-
ready: false,
|
|
73236
|
-
readyAt: null,
|
|
73237
|
-
readyStateKnown: false,
|
|
73238
|
-
pidPath: paths.pidPath,
|
|
73239
|
-
lockPath: paths.daemonLockPath,
|
|
73240
|
-
lockPid: current.lockPid,
|
|
73241
|
-
lockStale: current.lockStale,
|
|
73242
|
-
stopped: false
|
|
73243
|
-
};
|
|
73244
|
-
}
|
|
73245
|
-
const signalled = signalProcess(current.pid, "SIGTERM");
|
|
73246
|
-
let forced = false;
|
|
73247
|
-
let exited = !signalled || await waitForExit(current.pid, STOP_GRACE_MS);
|
|
73248
|
-
if (!exited) {
|
|
73249
|
-
forced = true;
|
|
73250
|
-
const killed = signalProcess(current.pid, "SIGKILL");
|
|
73251
|
-
exited = !killed || await waitForExit(current.pid, FORCE_KILL_GRACE_MS);
|
|
73252
|
-
}
|
|
73253
|
-
if (exited) {
|
|
73254
|
-
await removePid(paths.pidPath);
|
|
73255
|
-
}
|
|
73256
|
-
return {
|
|
73257
|
-
running: !exited,
|
|
73258
|
-
pid: current.pid,
|
|
73259
|
-
stale: false,
|
|
73260
|
-
capabilities: exited ? [] : current.capabilities,
|
|
73261
|
-
ready: !exited && current.ready,
|
|
73262
|
-
readyAt: !exited ? current.readyAt : null,
|
|
73263
|
-
readyStateKnown: !exited && current.readyStateKnown,
|
|
73264
|
-
pidPath: paths.pidPath,
|
|
73265
|
-
lockPath: paths.daemonLockPath,
|
|
73266
|
-
lockPid: current.lockPid,
|
|
73267
|
-
lockStale: current.lockStale,
|
|
73268
|
-
stopped: exited,
|
|
73269
|
-
forced
|
|
73270
|
-
};
|
|
73271
|
-
}
|
|
73272
|
-
async function ensureDaemonReady(options = {}) {
|
|
73273
|
-
const paths = resolveTaskPaths(options.homeDir);
|
|
73274
|
-
const commandName = options.commandName ?? "command";
|
|
73275
|
-
const timeoutMs = options.timeoutMs ?? readReadyTimeoutMs(options.env ?? process.env);
|
|
73276
|
-
let status = await getDaemonStatus(options.homeDir);
|
|
73277
|
-
let started = false;
|
|
73278
|
-
let logPath = paths.listenerLogPath;
|
|
73279
|
-
if (!status.running) {
|
|
73280
|
-
options.stderr?.write(`[okx-a2a] ${commandName} requires the daemon; starting daemon...
|
|
73281
|
-
`);
|
|
73282
|
-
const startResult = await startDaemon(options.homeDir);
|
|
73283
|
-
started = startResult.started;
|
|
73284
|
-
logPath = startResult.logPath;
|
|
73285
|
-
status = startResult;
|
|
73286
|
-
if (!status.running) {
|
|
73287
|
-
throw new Error(
|
|
73288
|
-
`${commandName} requires the daemon, but automatic daemon start failed. Check ${logPath} or run \`okx-a2a daemon restart\`.`
|
|
73289
|
-
);
|
|
73290
|
-
}
|
|
73291
|
-
status = await waitForDaemonReady({
|
|
73292
|
-
homeDir: options.homeDir,
|
|
73293
|
-
timeoutMs,
|
|
73294
|
-
requiredCapabilities: options.requiredCapabilities,
|
|
73295
|
-
requireKnownReadyState: true,
|
|
73296
|
-
logPath,
|
|
73297
|
-
commandName
|
|
73298
|
-
});
|
|
73299
|
-
options.stderr?.write(`[okx-a2a] daemon ready pid=${status.pid ?? "(unknown)"} log=${logPath}
|
|
73300
|
-
`);
|
|
73301
|
-
} else if (status.readyStateKnown && !status.ready) {
|
|
73302
|
-
status = await waitForDaemonReady({
|
|
73303
|
-
homeDir: options.homeDir,
|
|
73304
|
-
timeoutMs,
|
|
73305
|
-
requiredCapabilities: options.requiredCapabilities,
|
|
73306
|
-
requireKnownReadyState: false,
|
|
73307
|
-
logPath,
|
|
73308
|
-
commandName
|
|
73309
|
-
});
|
|
73310
|
-
}
|
|
73311
|
-
assertRequiredCapabilities(status, options.requiredCapabilities, commandName);
|
|
73312
|
-
return {
|
|
73313
|
-
...status,
|
|
73314
|
-
started,
|
|
73315
|
-
logPath
|
|
73316
|
-
};
|
|
73317
|
-
}
|
|
73318
|
-
async function waitForDaemonReady(options) {
|
|
73319
|
-
const deadline = Date.now() + Math.max(0, options.timeoutMs);
|
|
73320
|
-
let lastStatus = await getDaemonStatus(options.homeDir);
|
|
73321
|
-
while (Date.now() <= deadline) {
|
|
73322
|
-
const status = await getDaemonStatus(options.homeDir);
|
|
73323
|
-
lastStatus = status;
|
|
73324
|
-
if (!status.running) {
|
|
73325
|
-
if (status.stale) {
|
|
73326
|
-
throw new Error(
|
|
73327
|
-
`${options.commandName} requires the daemon, but the daemon exited before becoming ready. Check ${options.logPath} or run \`okx-a2a daemon restart\`.`
|
|
73328
|
-
);
|
|
73329
|
-
}
|
|
73330
|
-
} else if (isReadyForCommand(status, options.requiredCapabilities, options.requireKnownReadyState)) {
|
|
73331
|
-
return status;
|
|
73332
|
-
} else if (status.ready && findMissingCapabilities(status, options.requiredCapabilities).length > 0) {
|
|
73333
|
-
assertRequiredCapabilities(status, options.requiredCapabilities, options.commandName);
|
|
73334
|
-
}
|
|
73335
|
-
await sleep(Math.min(READY_POLL_MS, Math.max(1, deadline - Date.now() + 1)));
|
|
73336
|
-
}
|
|
73337
|
-
const missing = findMissingCapabilities(lastStatus, options.requiredCapabilities);
|
|
73338
|
-
const capabilitySuffix = missing.length > 0 ? ` missingCapabilities=${missing.join(",")}` : "";
|
|
73339
|
-
throw new Error(
|
|
73340
|
-
`${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\`.`
|
|
73341
|
-
);
|
|
73342
|
-
}
|
|
73343
|
-
function isReadyForCommand(status, requiredCapabilities, requireKnownReadyState = false) {
|
|
73344
|
-
if (!status.running) {
|
|
73345
|
-
return false;
|
|
73346
|
-
}
|
|
73347
|
-
if (requireKnownReadyState && !status.readyStateKnown) {
|
|
73348
|
-
return false;
|
|
73349
|
-
}
|
|
73350
|
-
if (status.readyStateKnown && !status.ready) {
|
|
73351
|
-
return false;
|
|
73352
|
-
}
|
|
73353
|
-
return findMissingCapabilities(status, requiredCapabilities).length === 0;
|
|
73354
|
-
}
|
|
73355
|
-
function assertRequiredCapabilities(status, requiredCapabilities, commandName) {
|
|
73356
|
-
const missing = findMissingCapabilities(status, requiredCapabilities);
|
|
73357
|
-
if (missing.length === 0) {
|
|
73358
|
-
return;
|
|
73359
|
-
}
|
|
73360
|
-
throw new Error(
|
|
73361
|
-
`${commandName} requires a daemon with ${missing.join(",")} support. Run \`okx-a2a daemon restart\` first.`
|
|
73362
|
-
);
|
|
73363
|
-
}
|
|
73364
|
-
function findMissingCapabilities(status, requiredCapabilities) {
|
|
73365
|
-
if (!requiredCapabilities || requiredCapabilities.length === 0) {
|
|
73366
|
-
return [];
|
|
73367
|
-
}
|
|
73368
|
-
return requiredCapabilities.filter((capability) => !status.capabilities.includes(capability));
|
|
73369
|
-
}
|
|
73370
|
-
function readReadyTimeoutMs(env) {
|
|
73371
|
-
const raw = env[DAEMON_READY_TIMEOUT_ENV]?.trim();
|
|
73372
|
-
if (!raw) {
|
|
73373
|
-
return DEFAULT_READY_TIMEOUT_MS;
|
|
73374
|
-
}
|
|
73375
|
-
const parsed = Number(raw);
|
|
73376
|
-
return Number.isFinite(parsed) && parsed > 0 ? parsed : DEFAULT_READY_TIMEOUT_MS;
|
|
73377
|
-
}
|
|
73378
|
-
function sleep(ms) {
|
|
73379
|
-
return new Promise((resolve6) => setTimeout(resolve6, ms));
|
|
73380
|
-
}
|
|
73482
|
+
init_daemon();
|
|
73381
73483
|
|
|
73382
73484
|
// src/ai-runner.ts
|
|
73383
73485
|
init_log();
|
|
@@ -73864,6 +73966,7 @@ var LogEvent = {
|
|
|
73864
73966
|
ONCHAINOS_CLI_ERROR: "Onchainos CLI error",
|
|
73865
73967
|
HEARTBEAT_FAILED: "Heartbeat failed",
|
|
73866
73968
|
HEARTBEAT_SKIPPED: "Heartbeat skipped",
|
|
73969
|
+
HEARTBEAT_GATEWAY_CHECK_FAILED: "Heartbeat gateway check failed",
|
|
73867
73970
|
MESSAGE_PARSE_FAILED: "Message parse failed",
|
|
73868
73971
|
MESSAGE_HANDLER_ERROR: "Message handler error",
|
|
73869
73972
|
OFFLINE_REPLAY_FAILED: "Offline replay failed",
|
|
@@ -86127,10 +86230,6 @@ function compareTimestamp(a, b) {
|
|
|
86127
86230
|
}
|
|
86128
86231
|
|
|
86129
86232
|
// ../core/src/xmtp-sdk/onchainos/agent-status.ts
|
|
86130
|
-
var XMTP_COMMUNICABLE_AGENT_STATUSES = /* @__PURE__ */ new Set([
|
|
86131
|
-
1 /* ACTIVE */,
|
|
86132
|
-
2 /* USER_OFFLINE */
|
|
86133
|
-
]);
|
|
86134
86233
|
var XMTP_BLOCKED_AGENT_STATUSES = /* @__PURE__ */ new Set([
|
|
86135
86234
|
3 /* SECURITY_BLACKLISTED */,
|
|
86136
86235
|
4 /* RISK_BLACKLISTED */,
|
|
@@ -86140,7 +86239,7 @@ function isAgentXmtpCommunicable(agent) {
|
|
|
86140
86239
|
if (!agent) {
|
|
86141
86240
|
return false;
|
|
86142
86241
|
}
|
|
86143
|
-
return
|
|
86242
|
+
return true;
|
|
86144
86243
|
}
|
|
86145
86244
|
function isAgentXmtpBlocked(agent) {
|
|
86146
86245
|
if (!agent) {
|
|
@@ -89305,7 +89404,7 @@ function buildConnectParams(config, instanceId, protocolVersion) {
|
|
|
89305
89404
|
client: {
|
|
89306
89405
|
id: "gateway-client",
|
|
89307
89406
|
displayName: "okx-a2a-node",
|
|
89308
|
-
version: "0.1.
|
|
89407
|
+
version: "0.1.6-beta-c3024b2b0b-260706164140",
|
|
89309
89408
|
platform: "node",
|
|
89310
89409
|
mode: "backend",
|
|
89311
89410
|
instanceId
|
|
@@ -89316,7 +89415,7 @@ function buildConnectParams(config, instanceId, protocolVersion) {
|
|
|
89316
89415
|
commands: [],
|
|
89317
89416
|
permissions: {},
|
|
89318
89417
|
locale: Intl.DateTimeFormat().resolvedOptions().locale || "en-US",
|
|
89319
|
-
userAgent: `okx-a2a-node/${"0.1.
|
|
89418
|
+
userAgent: `okx-a2a-node/${"0.1.6-beta-c3024b2b0b-260706164140"}`,
|
|
89320
89419
|
auth: {
|
|
89321
89420
|
...config.token ? { token: config.token } : {},
|
|
89322
89421
|
...config.password ? { password: config.password } : {}
|
|
@@ -93780,13 +93879,14 @@ function userWatchEventDeliveredSentryExtra(event) {
|
|
|
93780
93879
|
}
|
|
93781
93880
|
|
|
93782
93881
|
// src/listener.ts
|
|
93882
|
+
init_daemon_lock();
|
|
93783
93883
|
init_ai_provider();
|
|
93784
93884
|
|
|
93785
93885
|
// ../core/src/sentry-config.ts
|
|
93786
93886
|
var environment = process.env.SENTRY_ENV === "dev" ? "dev" : "prod";
|
|
93787
93887
|
var SENTRY_CONFIG = {
|
|
93788
93888
|
projectName: "okx/openclaw-okx-a2a-extension",
|
|
93789
|
-
release: "0.1.
|
|
93889
|
+
release: "0.1.6-beta-c3024b2b0b-260706164140",
|
|
93790
93890
|
environment
|
|
93791
93891
|
};
|
|
93792
93892
|
|
|
@@ -93826,20 +93926,31 @@ async function isGatewayAvailableForHeartbeat(options) {
|
|
|
93826
93926
|
}
|
|
93827
93927
|
return isHermesGatewayPluginEnabled({ env: options.env });
|
|
93828
93928
|
}
|
|
93829
|
-
async function
|
|
93929
|
+
async function getHermesGatewayPluginStatus(options = {}) {
|
|
93830
93930
|
const env = options.env ?? process.env;
|
|
93831
|
-
if (options.requireGatewayRuntime && detectGatewayInvocation(env) !== "hermes") {
|
|
93832
|
-
return false;
|
|
93833
|
-
}
|
|
93834
93931
|
const hermesHome = env.HERMES_HOME?.trim() || (0, import_node_path21.join)((0, import_node_os6.homedir)(), ".hermes");
|
|
93835
|
-
|
|
93836
|
-
|
|
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 };
|
|
93837
93935
|
}
|
|
93936
|
+
const configPath = (0, import_node_path21.join)(hermesHome, "config.yaml");
|
|
93937
|
+
let content3;
|
|
93838
93938
|
try {
|
|
93839
|
-
|
|
93939
|
+
content3 = await (0, import_promises6.readFile)(configPath, "utf8");
|
|
93840
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") {
|
|
93841
93951
|
return false;
|
|
93842
93952
|
}
|
|
93953
|
+
return (await getHermesGatewayPluginStatus({ env })).enabled;
|
|
93843
93954
|
}
|
|
93844
93955
|
function hermesConfigEnablesOkxA2a(content3) {
|
|
93845
93956
|
let inPlugins = false;
|
|
@@ -94013,12 +94124,12 @@ async function runListenerWithLock(options, paths) {
|
|
|
94013
94124
|
}));
|
|
94014
94125
|
}
|
|
94015
94126
|
});
|
|
94016
|
-
service.setPluginVersion("0.1.
|
|
94127
|
+
service.setPluginVersion("0.1.6-beta-c3024b2b0b-260706164140");
|
|
94017
94128
|
await service.init();
|
|
94018
94129
|
const pluginVersionStatus = service.pluginVersionStatus;
|
|
94019
94130
|
if (pluginVersionStatus.unavailable) {
|
|
94020
94131
|
throw new Error(
|
|
94021
|
-
`@okxweb3/a2a-node v${"0.1.
|
|
94132
|
+
`@okxweb3/a2a-node v${"0.1.6-beta-c3024b2b0b-260706164140"} is below the required minimum v${pluginVersionStatus.minVersion}`
|
|
94022
94133
|
);
|
|
94023
94134
|
}
|
|
94024
94135
|
const systemConfig = service.getSystemConfig();
|
|
@@ -94036,7 +94147,7 @@ async function runListenerWithLock(options, paths) {
|
|
|
94036
94147
|
onchainosAgentId: "*",
|
|
94037
94148
|
reason: "system-config missing sentryDsn",
|
|
94038
94149
|
pluginId: "@okxweb3/a2a-node",
|
|
94039
|
-
pluginVersion: "0.1.
|
|
94150
|
+
pluginVersion: "0.1.6-beta-c3024b2b0b-260706164140"
|
|
94040
94151
|
});
|
|
94041
94152
|
}
|
|
94042
94153
|
logWithTimestamp(
|
|
@@ -94076,7 +94187,28 @@ async function runListenerWithLock(options, paths) {
|
|
|
94076
94187
|
const hasActiveAgents = service.getClients().size > 0;
|
|
94077
94188
|
let shouldHeartbeat = hasActiveAgents;
|
|
94078
94189
|
const heartbeatProvider = resolveConfiguredAiProvider({ store: sessionStore }) ?? detectGatewayInvocation();
|
|
94079
|
-
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) {
|
|
94080
94212
|
const gatewayAvailable = await isGatewayAvailableForHeartbeat({
|
|
94081
94213
|
provider: heartbeatProvider
|
|
94082
94214
|
});
|
|
@@ -94398,7 +94530,7 @@ init_update_cli();
|
|
|
94398
94530
|
init_win_spawn();
|
|
94399
94531
|
|
|
94400
94532
|
// src/log-tail.ts
|
|
94401
|
-
var
|
|
94533
|
+
var import_node_fs18 = require("node:fs");
|
|
94402
94534
|
var import_promises8 = require("node:fs/promises");
|
|
94403
94535
|
var import_node_string_decoder = require("node:string_decoder");
|
|
94404
94536
|
init_win_spawn();
|
|
@@ -94522,7 +94654,7 @@ async function followFile(filePath, onData, options = {}) {
|
|
|
94522
94654
|
void check();
|
|
94523
94655
|
}, pollIntervalMs);
|
|
94524
94656
|
try {
|
|
94525
|
-
watcher = (0,
|
|
94657
|
+
watcher = (0, import_node_fs18.watch)(filePath, () => {
|
|
94526
94658
|
void check();
|
|
94527
94659
|
});
|
|
94528
94660
|
watcher.on("error", (error) => {
|
|
@@ -94588,8 +94720,6 @@ init_ai_provider();
|
|
|
94588
94720
|
init_update_cli();
|
|
94589
94721
|
|
|
94590
94722
|
// src/doctor-cli.ts
|
|
94591
|
-
var import_node_fs21 = require("node:fs");
|
|
94592
|
-
var import_node_os10 = require("node:os");
|
|
94593
94723
|
var import_node_path26 = require("node:path");
|
|
94594
94724
|
init_log();
|
|
94595
94725
|
init_win_compat();
|
|
@@ -94597,18 +94727,18 @@ init_ai_command();
|
|
|
94597
94727
|
init_ai_provider();
|
|
94598
94728
|
|
|
94599
94729
|
// src/autostart.ts
|
|
94600
|
-
var
|
|
94601
|
-
var
|
|
94730
|
+
var import_node_child_process8 = require("node:child_process");
|
|
94731
|
+
var import_node_fs20 = require("node:fs");
|
|
94602
94732
|
var import_promises10 = require("node:fs/promises");
|
|
94603
|
-
var
|
|
94604
|
-
var
|
|
94733
|
+
var import_node_os9 = require("node:os");
|
|
94734
|
+
var import_node_path25 = require("node:path");
|
|
94605
94735
|
var import_node_util2 = require("node:util");
|
|
94606
94736
|
|
|
94607
94737
|
// src/autostart-windows.ts
|
|
94608
|
-
var
|
|
94609
|
-
var
|
|
94738
|
+
var import_node_child_process7 = require("node:child_process");
|
|
94739
|
+
var import_node_fs19 = require("node:fs");
|
|
94610
94740
|
var import_promises9 = require("node:fs/promises");
|
|
94611
|
-
var
|
|
94741
|
+
var import_node_path24 = require("node:path");
|
|
94612
94742
|
init_log();
|
|
94613
94743
|
init_paths();
|
|
94614
94744
|
init_win_spawn();
|
|
@@ -94619,10 +94749,10 @@ var SCHTASKS_TIMEOUT_MS = 15e3;
|
|
|
94619
94749
|
var LOG_SNIPPET_LIMIT = 500;
|
|
94620
94750
|
function resolveWindowsAutostartPaths(homeDir) {
|
|
94621
94751
|
const resolvedHome = homeDir ?? resolveTaskPaths().homeDir;
|
|
94622
|
-
const autostartDir = (0,
|
|
94752
|
+
const autostartDir = (0, import_node_path24.join)(resolvedHome, "autostart");
|
|
94623
94753
|
return {
|
|
94624
94754
|
autostartDir,
|
|
94625
|
-
vbsPath: (0,
|
|
94755
|
+
vbsPath: (0, import_node_path24.join)(autostartDir, VBS_FILE_NAME)
|
|
94626
94756
|
};
|
|
94627
94757
|
}
|
|
94628
94758
|
function escapeVbsString(value) {
|
|
@@ -94654,7 +94784,7 @@ function buildAutostartVbs(options) {
|
|
|
94654
94784
|
`;
|
|
94655
94785
|
}
|
|
94656
94786
|
function isWindowsElevated() {
|
|
94657
|
-
const result = (0,
|
|
94787
|
+
const result = (0, import_node_child_process7.spawnSync)("net", ["session"], {
|
|
94658
94788
|
windowsHide: true,
|
|
94659
94789
|
encoding: "utf8",
|
|
94660
94790
|
timeout: 5e3,
|
|
@@ -94699,10 +94829,10 @@ function resolveWindowsCliPath() {
|
|
|
94699
94829
|
logWinCompat(`${WIN_COMPAT_LOG_PREFIX} autostart: process.argv[1] is empty, cannot resolve okx-a2a CLI path`);
|
|
94700
94830
|
throw new Error("Unable to resolve current okx-a2a CLI path");
|
|
94701
94831
|
}
|
|
94702
|
-
return (0,
|
|
94832
|
+
return (0, import_node_path24.resolve)(entry);
|
|
94703
94833
|
}
|
|
94704
94834
|
function runSchtasks(operation, args) {
|
|
94705
|
-
const result = (0,
|
|
94835
|
+
const result = (0, import_node_child_process7.spawnSync)(SCHTASKS_BIN, args, {
|
|
94706
94836
|
windowsHide: true,
|
|
94707
94837
|
encoding: "utf8",
|
|
94708
94838
|
timeout: SCHTASKS_TIMEOUT_MS
|
|
@@ -94740,10 +94870,10 @@ async function installWindowsAutostart() {
|
|
|
94740
94870
|
const execPath = process.execPath;
|
|
94741
94871
|
const cliPath = resolveWindowsCliPath();
|
|
94742
94872
|
const pathValue = process.env.PATH?.trim() || "";
|
|
94743
|
-
if (!(0,
|
|
94873
|
+
if (!(0, import_node_fs19.existsSync)(execPath)) {
|
|
94744
94874
|
throw new Error(`autostart: node executable not found at ${execPath}`);
|
|
94745
94875
|
}
|
|
94746
|
-
if (!(0,
|
|
94876
|
+
if (!(0, import_node_fs19.existsSync)(cliPath)) {
|
|
94747
94877
|
throw new Error(`autostart: okx-a2a CLI entry not found at ${cliPath}`);
|
|
94748
94878
|
}
|
|
94749
94879
|
await (0, import_promises9.mkdir)(paths.autostartDir, { recursive: true });
|
|
@@ -94778,22 +94908,22 @@ function isWindowsAutostartInstalled() {
|
|
|
94778
94908
|
|
|
94779
94909
|
// src/autostart.ts
|
|
94780
94910
|
init_paths();
|
|
94781
|
-
var execFileAsync2 = (0, import_node_util2.promisify)(
|
|
94911
|
+
var execFileAsync2 = (0, import_node_util2.promisify)(import_node_child_process8.execFile);
|
|
94782
94912
|
var SERVICE_NAME = "okx-a2a.service";
|
|
94783
94913
|
var LAUNCHD_LABEL = "com.okx.a2a";
|
|
94784
94914
|
var LAUNCHD_PLIST_NAME = `${LAUNCHD_LABEL}.plist`;
|
|
94785
|
-
function resolveSystemdAutostartPaths(home = (0,
|
|
94786
|
-
const serviceDir = (0,
|
|
94915
|
+
function resolveSystemdAutostartPaths(home = (0, import_node_os9.homedir)()) {
|
|
94916
|
+
const serviceDir = (0, import_node_path25.join)(home, ".config", "systemd", "user");
|
|
94787
94917
|
return {
|
|
94788
94918
|
serviceDir,
|
|
94789
|
-
servicePath: (0,
|
|
94919
|
+
servicePath: (0, import_node_path25.join)(serviceDir, SERVICE_NAME)
|
|
94790
94920
|
};
|
|
94791
94921
|
}
|
|
94792
|
-
function resolveLaunchdAutostartPaths(home = (0,
|
|
94793
|
-
const agentDir = (0,
|
|
94922
|
+
function resolveLaunchdAutostartPaths(home = (0, import_node_os9.homedir)()) {
|
|
94923
|
+
const agentDir = (0, import_node_path25.join)(home, "Library", "LaunchAgents");
|
|
94794
94924
|
return {
|
|
94795
94925
|
agentDir,
|
|
94796
|
-
plistPath: (0,
|
|
94926
|
+
plistPath: (0, import_node_path25.join)(agentDir, LAUNCHD_PLIST_NAME)
|
|
94797
94927
|
};
|
|
94798
94928
|
}
|
|
94799
94929
|
function quoteSystemdArg(value) {
|
|
@@ -94807,7 +94937,7 @@ function resolveCliPath() {
|
|
|
94807
94937
|
if (!entry) {
|
|
94808
94938
|
throw new Error("Unable to resolve current okx-a2a CLI path");
|
|
94809
94939
|
}
|
|
94810
|
-
return (0,
|
|
94940
|
+
return (0, import_node_path25.resolve)(entry);
|
|
94811
94941
|
}
|
|
94812
94942
|
function buildSystemdUserService() {
|
|
94813
94943
|
const taskHome2 = resolveTaskHome();
|
|
@@ -94942,10 +95072,10 @@ async function installAutostart() {
|
|
|
94942
95072
|
}
|
|
94943
95073
|
function isAutostartInstalled() {
|
|
94944
95074
|
if (process.platform === "linux") {
|
|
94945
|
-
return (0,
|
|
95075
|
+
return (0, import_node_fs20.existsSync)(resolveSystemdAutostartPaths().servicePath);
|
|
94946
95076
|
}
|
|
94947
95077
|
if (process.platform === "darwin") {
|
|
94948
|
-
return (0,
|
|
95078
|
+
return (0, import_node_fs20.existsSync)(resolveLaunchdAutostartPaths().plistPath);
|
|
94949
95079
|
}
|
|
94950
95080
|
if (process.platform === "win32") {
|
|
94951
95081
|
return isWindowsAutostartInstalled();
|
|
@@ -94953,7 +95083,11 @@ function isAutostartInstalled() {
|
|
|
94953
95083
|
return false;
|
|
94954
95084
|
}
|
|
94955
95085
|
|
|
95086
|
+
// src/doctor-cli.ts
|
|
95087
|
+
init_daemon();
|
|
95088
|
+
|
|
94956
95089
|
// src/daemon-ops.ts
|
|
95090
|
+
init_daemon();
|
|
94957
95091
|
async function refreshAgentsAndWait(timeoutMs = 6e4) {
|
|
94958
95092
|
const status = await getDaemonStatus();
|
|
94959
95093
|
if (!status.running) {
|
|
@@ -95010,7 +95144,9 @@ async function dispatchRuntimeSwitchUserMessage(store, result) {
|
|
|
95010
95144
|
// src/doctor-cli.ts
|
|
95011
95145
|
init_session_store();
|
|
95012
95146
|
init_update_cli();
|
|
95147
|
+
init_win_native_launcher();
|
|
95013
95148
|
init_win_spawn();
|
|
95149
|
+
init_win_native_launcher();
|
|
95014
95150
|
var DOCTOR_MIN_NODE_VERSION = "22.14.0";
|
|
95015
95151
|
var DOCTOR_DAEMON_READY_TIMEOUT_MS = 2e4;
|
|
95016
95152
|
var NODE_PACKAGE_SPEC = "@okxweb3/a2a-node";
|
|
@@ -95220,22 +95356,6 @@ var cliVersionChecker = {
|
|
|
95220
95356
|
return `npm install completed; installed version could not be verified from npm metadata (was ${before}) \u2014 daemon will be restarted to be safe`;
|
|
95221
95357
|
}
|
|
95222
95358
|
};
|
|
95223
|
-
function findWindowsNativeOkxA2aExe(pathValue, appData, userProfile, fileExists2 = import_node_fs21.existsSync) {
|
|
95224
|
-
const dirs = pathValue.split(";").map((d) => d.trim()).filter(Boolean);
|
|
95225
|
-
if (appData) {
|
|
95226
|
-
dirs.push((0, import_node_path26.join)(appData, "npm"));
|
|
95227
|
-
}
|
|
95228
|
-
if (userProfile) {
|
|
95229
|
-
dirs.push((0, import_node_path26.join)(userProfile, ".local", "bin"));
|
|
95230
|
-
}
|
|
95231
|
-
for (const dir of dirs) {
|
|
95232
|
-
const candidate = (0, import_node_path26.join)(dir, "okx-a2a.exe");
|
|
95233
|
-
if (fileExists2(candidate)) {
|
|
95234
|
-
return candidate;
|
|
95235
|
-
}
|
|
95236
|
-
}
|
|
95237
|
-
return null;
|
|
95238
|
-
}
|
|
95239
95359
|
var windowsNativeLauncherChecker = {
|
|
95240
95360
|
id: "windows_native_launcher",
|
|
95241
95361
|
title: "Windows native launcher (okx-a2a.exe)",
|
|
@@ -95272,27 +95392,13 @@ var windowsNativeLauncherChecker = {
|
|
|
95272
95392
|
};
|
|
95273
95393
|
},
|
|
95274
95394
|
applyFix: async (ctx) => {
|
|
95275
|
-
const
|
|
95276
|
-
|
|
95277
|
-
|
|
95278
|
-
|
|
95279
|
-
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}`;
|
|
95280
95400
|
}
|
|
95281
95401
|
};
|
|
95282
|
-
function resolveRunningCliPath() {
|
|
95283
|
-
const fromArgv = process.argv[1];
|
|
95284
|
-
if (fromArgv && /(?:^|[\\/])cli\.js$/.test(fromArgv) && (0, import_node_fs21.existsSync)(fromArgv)) {
|
|
95285
|
-
return fromArgv;
|
|
95286
|
-
}
|
|
95287
|
-
const beside = (0, import_node_path26.join)(__dirname, "cli.js");
|
|
95288
|
-
if ((0, import_node_fs21.existsSync)(beside)) {
|
|
95289
|
-
return beside;
|
|
95290
|
-
}
|
|
95291
|
-
if (fromArgv) {
|
|
95292
|
-
return fromArgv;
|
|
95293
|
-
}
|
|
95294
|
-
throw new Error("could not resolve the running okx-a2a CLI path for the native launcher");
|
|
95295
|
-
}
|
|
95296
95402
|
var providerBindingChecker = {
|
|
95297
95403
|
id: "provider_binding",
|
|
95298
95404
|
title: "Default AI provider binding",
|
|
@@ -95312,13 +95418,18 @@ var providerBindingChecker = {
|
|
|
95312
95418
|
data: { bound, detectedRuntime: runtime }
|
|
95313
95419
|
};
|
|
95314
95420
|
}
|
|
95421
|
+
const autoFixCanSucceed = !!expected;
|
|
95315
95422
|
return {
|
|
95316
95423
|
id: "provider_binding",
|
|
95317
95424
|
title: "Default AI provider binding",
|
|
95318
95425
|
status: "fail",
|
|
95319
95426
|
severity: "required",
|
|
95320
95427
|
detail: bound ? `default provider ${bound} does not match the detected runtime ${runtime}` : "no default AI provider is bound",
|
|
95321
|
-
fix: { kind: "auto", description: "Run the in-memory runtime switch (equivalent of `okx-a2a switch-runtime`)." }
|
|
95428
|
+
fix: autoFixCanSucceed ? { kind: "auto", description: "Run the in-memory runtime switch (equivalent of `okx-a2a switch-runtime`)." } : {
|
|
95429
|
+
kind: "manual",
|
|
95430
|
+
description: "No AI runtime detected and no default provider is bound. Run doctor from your AI environment (OpenClaw / Codex / Claude / Hermes), or bind one manually first.",
|
|
95431
|
+
command: "okx-a2a ai-provider set --provider <codex|claude|hermes|openclaw>"
|
|
95432
|
+
},
|
|
95322
95433
|
data: { bound, detectedRuntime: runtime }
|
|
95323
95434
|
};
|
|
95324
95435
|
} finally {
|
|
@@ -95330,7 +95441,7 @@ var providerBindingChecker = {
|
|
|
95330
95441
|
try {
|
|
95331
95442
|
const result = await performRuntimeSwitch(store);
|
|
95332
95443
|
if (!result.ok) {
|
|
95333
|
-
throw new Error(result.message || "runtime switch failed");
|
|
95444
|
+
throw new Error(result.userMessage || result.message || "runtime switch failed");
|
|
95334
95445
|
}
|
|
95335
95446
|
return `runtime switch: provider=${result.provider} ${result.changed ? "(switched)" : "(already current)"}`;
|
|
95336
95447
|
} finally {
|
|
@@ -95391,7 +95502,14 @@ var providerCliChecker = {
|
|
|
95391
95502
|
status: "fail",
|
|
95392
95503
|
severity: "required",
|
|
95393
95504
|
detail: `${provider} CLI at ${resolved} is not logged in (${auth.reason})`,
|
|
95394
|
-
|
|
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
|
+
} : {
|
|
95395
95513
|
kind: "auto",
|
|
95396
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.",
|
|
95397
95515
|
command: loginCommand
|
|
@@ -95430,6 +95548,11 @@ var providerCliChecker = {
|
|
|
95430
95548
|
}
|
|
95431
95549
|
const auth = provider === "codex" ? await checkCodexCliAuthStatus(resolved) : await checkClaudeCliAuthStatus(resolved);
|
|
95432
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
|
+
}
|
|
95433
95556
|
errorWithTimestamp(`[doctor] launching ${provider} CLI login (interactive; waiting for completion)`);
|
|
95434
95557
|
const login = await runProviderLoginInteractive(provider, resolved);
|
|
95435
95558
|
if (!login.ok) {
|
|
@@ -95453,13 +95576,14 @@ var gatewayPluginChecker = {
|
|
|
95453
95576
|
return null;
|
|
95454
95577
|
}
|
|
95455
95578
|
const installed = await isGatewayPluginInstalled(ctx.target);
|
|
95579
|
+
const hermesPathSuffix = ctx.target === "hermes" ? ` (checked ${resolveHermesPluginYamlPath()})` : "";
|
|
95456
95580
|
if (installed) {
|
|
95457
95581
|
return {
|
|
95458
95582
|
id: "gateway_plugin",
|
|
95459
95583
|
title: "Gateway plugin installed",
|
|
95460
95584
|
status: "pass",
|
|
95461
95585
|
severity: "required",
|
|
95462
|
-
detail: `${ctx.target} okx-a2a plugin is installed`
|
|
95586
|
+
detail: `${ctx.target} okx-a2a plugin is installed${hermesPathSuffix}`
|
|
95463
95587
|
};
|
|
95464
95588
|
}
|
|
95465
95589
|
const hermesOnWindows = ctx.target === "hermes" && ctx.platform === "win32";
|
|
@@ -95468,7 +95592,7 @@ var gatewayPluginChecker = {
|
|
|
95468
95592
|
title: "Gateway plugin installed",
|
|
95469
95593
|
status: "fail",
|
|
95470
95594
|
severity: "required",
|
|
95471
|
-
detail: `${ctx.target} okx-a2a plugin is not installed`,
|
|
95595
|
+
detail: `${ctx.target} okx-a2a plugin is not installed${hermesPathSuffix}`,
|
|
95472
95596
|
fix: hermesOnWindows ? {
|
|
95473
95597
|
kind: "manual",
|
|
95474
95598
|
description: "Hermes plugin installation requires bash and is not supported on Windows. Use WSL or run setup on macOS/Linux."
|
|
@@ -95497,13 +95621,14 @@ var gatewayConfigChecker = {
|
|
|
95497
95621
|
return null;
|
|
95498
95622
|
}
|
|
95499
95623
|
const drift = ctx.target === "openclaw" ? await ensureOpenClawOkxA2aPluginConfig({ dryRun: true }) : await ensureHermesOkxA2aPluginConfig(void 0, { dryRun: true });
|
|
95624
|
+
const hermesPathSuffix = ctx.target === "hermes" ? ` (checked ${resolveHermesConfigPath()})` : "";
|
|
95500
95625
|
if (!drift) {
|
|
95501
95626
|
return {
|
|
95502
95627
|
id: "gateway_config",
|
|
95503
95628
|
title: "Gateway plugin config",
|
|
95504
95629
|
status: "pass",
|
|
95505
95630
|
severity: "required",
|
|
95506
|
-
detail: `${ctx.target} okx-a2a plugin config is normalized`
|
|
95631
|
+
detail: `${ctx.target} okx-a2a plugin config is normalized${hermesPathSuffix}`
|
|
95507
95632
|
};
|
|
95508
95633
|
}
|
|
95509
95634
|
return {
|
|
@@ -95511,7 +95636,7 @@ var gatewayConfigChecker = {
|
|
|
95511
95636
|
title: "Gateway plugin config",
|
|
95512
95637
|
status: "fail",
|
|
95513
95638
|
severity: "required",
|
|
95514
|
-
detail: `${ctx.target} okx-a2a plugin config needs normalization`,
|
|
95639
|
+
detail: `${ctx.target} okx-a2a plugin config needs normalization${hermesPathSuffix}`,
|
|
95515
95640
|
fix: { kind: "auto", description: `Apply the ${ctx.target} config normalization in-process.` }
|
|
95516
95641
|
};
|
|
95517
95642
|
},
|
|
@@ -95759,8 +95884,9 @@ async function runDoctor(options = {}) {
|
|
|
95759
95884
|
platform: options.platform ?? process.platform,
|
|
95760
95885
|
env: options.env ?? process.env,
|
|
95761
95886
|
target: options.target ?? resolveDoctorTarget(options.env ?? process.env),
|
|
95762
|
-
cliVersion: options.cliVersion ?? (true ? "0.1.
|
|
95887
|
+
cliVersion: options.cliVersion ?? (true ? "0.1.6-beta-c3024b2b0b-260706164140" : "0.0.0"),
|
|
95763
95888
|
fixMode: options.fix === true,
|
|
95889
|
+
nonInteractive: options.nonInteractive === true,
|
|
95764
95890
|
packageChanged: false
|
|
95765
95891
|
};
|
|
95766
95892
|
const checkers = options.checkers ?? CHECKERS;
|
|
@@ -95907,6 +96033,7 @@ function formatDoctorReportForHumans(report) {
|
|
|
95907
96033
|
async function handleDoctorCommand(args) {
|
|
95908
96034
|
const json = args.includes("--json");
|
|
95909
96035
|
const fix = args.includes("--fix");
|
|
96036
|
+
const nonInteractive = args.includes("--non-interactive");
|
|
95910
96037
|
const targetIndex = args.indexOf("--target");
|
|
95911
96038
|
const rawTarget = targetIndex >= 0 ? args[targetIndex + 1] : void 0;
|
|
95912
96039
|
if (targetIndex >= 0 && (rawTarget === void 0 || rawTarget.startsWith("--"))) {
|
|
@@ -95930,7 +96057,7 @@ async function handleDoctorCommand(args) {
|
|
|
95930
96057
|
};
|
|
95931
96058
|
let report;
|
|
95932
96059
|
try {
|
|
95933
|
-
report = await runDoctor({ fix, ...rawTarget ? { target: rawTarget } : {} });
|
|
96060
|
+
report = await runDoctor({ fix, nonInteractive, ...rawTarget ? { target: rawTarget } : {} });
|
|
95934
96061
|
} catch (error) {
|
|
95935
96062
|
restoreStdout();
|
|
95936
96063
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -96036,12 +96163,14 @@ init_win_native_launcher();
|
|
|
96036
96163
|
ensureDaemonReady,
|
|
96037
96164
|
ensureDefaultAiProvider,
|
|
96038
96165
|
ensureOpenClawOkxA2aPluginConfig,
|
|
96166
|
+
ensureWindowsNativeLauncher,
|
|
96039
96167
|
extractAiSessionId,
|
|
96040
96168
|
extractXmtpSentAtMs,
|
|
96041
96169
|
findWindowsNativeOkxA2aExe,
|
|
96042
96170
|
followFile,
|
|
96043
96171
|
formatDoctorReportForHumans,
|
|
96044
96172
|
getDaemonStatus,
|
|
96173
|
+
getHermesGatewayPluginStatus,
|
|
96045
96174
|
handleDoctorCommand,
|
|
96046
96175
|
handleXmtpSendCommand,
|
|
96047
96176
|
hasAiRuntimeMarker,
|