├── .readme ├── installation │ ├── enable.png │ ├── enable_done.png │ ├── menu.png │ └── scan_directory.png ├── logo │ ├── agplv3.png │ ├── initMAX_banner.png │ ├── zabbix-certified-trainer.png │ └── zabbix-premium-partner.png └── screen │ ├── ChatGPT_widget.gif │ ├── config_popup.png │ └── dashboard.png ├── LICENSE.md ├── README.md ├── Widget.php ├── actions └── WidgetView.php ├── assets ├── css │ ├── form.css │ └── widget.css ├── font │ ├── rubik-regular.ttf │ ├── rubik-regular.woff │ └── rubik-regular.woff2 ├── img │ ├── avatar-chatgpt.png │ ├── avatar-initmax.png │ ├── background.png │ ├── initmax-free.svg │ └── initmax.svg └── js │ ├── class.widget.js │ └── marked.min.js ├── includes └── WidgetForm.php ├── manifest.json ├── package-lock.json ├── package.json └── views ├── widget.edit.js.php ├── widget.edit.php └── widget.view.php /.readme/installation/enable.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/initMAX/Zabbix-UI-Widgets-ChatGPT/78eff010c95bbbb077f1661098d91d97b75ccabc/.readme/installation/enable.png -------------------------------------------------------------------------------- /.readme/installation/enable_done.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/initMAX/Zabbix-UI-Widgets-ChatGPT/78eff010c95bbbb077f1661098d91d97b75ccabc/.readme/installation/enable_done.png -------------------------------------------------------------------------------- /.readme/installation/menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/initMAX/Zabbix-UI-Widgets-ChatGPT/78eff010c95bbbb077f1661098d91d97b75ccabc/.readme/installation/menu.png -------------------------------------------------------------------------------- /.readme/installation/scan_directory.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/initMAX/Zabbix-UI-Widgets-ChatGPT/78eff010c95bbbb077f1661098d91d97b75ccabc/.readme/installation/scan_directory.png -------------------------------------------------------------------------------- /.readme/logo/agplv3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/initMAX/Zabbix-UI-Widgets-ChatGPT/78eff010c95bbbb077f1661098d91d97b75ccabc/.readme/logo/agplv3.png -------------------------------------------------------------------------------- /.readme/logo/initMAX_banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/initMAX/Zabbix-UI-Widgets-ChatGPT/78eff010c95bbbb077f1661098d91d97b75ccabc/.readme/logo/initMAX_banner.png -------------------------------------------------------------------------------- /.readme/logo/zabbix-certified-trainer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/initMAX/Zabbix-UI-Widgets-ChatGPT/78eff010c95bbbb077f1661098d91d97b75ccabc/.readme/logo/zabbix-certified-trainer.png -------------------------------------------------------------------------------- /.readme/logo/zabbix-premium-partner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/initMAX/Zabbix-UI-Widgets-ChatGPT/78eff010c95bbbb077f1661098d91d97b75ccabc/.readme/logo/zabbix-premium-partner.png -------------------------------------------------------------------------------- /.readme/screen/ChatGPT_widget.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/initMAX/Zabbix-UI-Widgets-ChatGPT/78eff010c95bbbb077f1661098d91d97b75ccabc/.readme/screen/ChatGPT_widget.gif -------------------------------------------------------------------------------- /.readme/screen/config_popup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/initMAX/Zabbix-UI-Widgets-ChatGPT/78eff010c95bbbb077f1661098d91d97b75ccabc/.readme/screen/config_popup.png -------------------------------------------------------------------------------- /.readme/screen/dashboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/initMAX/Zabbix-UI-Widgets-ChatGPT/78eff010c95bbbb077f1661098d91d97b75ccabc/.readme/screen/dashboard.png -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | 2 |

3 | 4 | # GNU AFFERO GENERAL PUBLIC LICENSE 5 | 6 | Version 3, 19 November 2007 7 | 8 | Copyright (C) 2007 Free Software Foundation, Inc. 9 | 10 | 11 | Everyone is permitted to copy and distribute verbatim copies of this 12 | license document, but changing it is not allowed. 13 | 14 | ## Preamble 15 | 16 | The GNU Affero General Public License is a free, copyleft license for 17 | software and other kinds of works, specifically designed to ensure 18 | cooperation with the community in the case of network server software. 19 | 20 | The licenses for most software and other practical works are designed 21 | to take away your freedom to share and change the works. By contrast, 22 | our General Public Licenses are intended to guarantee your freedom to 23 | share and change all versions of a program--to make sure it remains 24 | free software for all its users. 25 | 26 | When we speak of free software, we are referring to freedom, not 27 | price. Our General Public Licenses are designed to make sure that you 28 | have the freedom to distribute copies of free software (and charge for 29 | them if you wish), that you receive source code or can get it if you 30 | want it, that you can change the software or use pieces of it in new 31 | free programs, and that you know you can do these things. 32 | 33 | Developers that use our General Public Licenses protect your rights 34 | with two steps: (1) assert copyright on the software, and (2) offer 35 | you this License which gives you legal permission to copy, distribute 36 | and/or modify the software. 37 | 38 | A secondary benefit of defending all users' freedom is that 39 | improvements made in alternate versions of the program, if they 40 | receive widespread use, become available for other developers to 41 | incorporate. Many developers of free software are heartened and 42 | encouraged by the resulting cooperation. However, in the case of 43 | software used on network servers, this result may fail to come about. 44 | The GNU General Public License permits making a modified version and 45 | letting the public access it on a server without ever releasing its 46 | source code to the public. 47 | 48 | The GNU Affero General Public License is designed specifically to 49 | ensure that, in such cases, the modified source code becomes available 50 | to the community. It requires the operator of a network server to 51 | provide the source code of the modified version running there to the 52 | users of that server. Therefore, public use of a modified version, on 53 | a publicly accessible server, gives the public access to the source 54 | code of the modified version. 55 | 56 | An older license, called the Affero General Public License and 57 | published by Affero, was designed to accomplish similar goals. This is 58 | a different license, not a version of the Affero GPL, but Affero has 59 | released a new version of the Affero GPL which permits relicensing 60 | under this license. 61 | 62 | The precise terms and conditions for copying, distribution and 63 | modification follow. 64 | 65 | ## TERMS AND CONDITIONS 66 | 67 | ### 0. Definitions. 68 | 69 | "This License" refers to version 3 of the GNU Affero General Public 70 | License. 71 | 72 | "Copyright" also means copyright-like laws that apply to other kinds 73 | of works, such as semiconductor masks. 74 | 75 | "The Program" refers to any copyrightable work licensed under this 76 | License. Each licensee is addressed as "you". "Licensees" and 77 | "recipients" may be individuals or organizations. 78 | 79 | To "modify" a work means to copy from or adapt all or part of the work 80 | in a fashion requiring copyright permission, other than the making of 81 | an exact copy. The resulting work is called a "modified version" of 82 | the earlier work or a work "based on" the earlier work. 83 | 84 | A "covered work" means either the unmodified Program or a work based 85 | on the Program. 86 | 87 | To "propagate" a work means to do anything with it that, without 88 | permission, would make you directly or secondarily liable for 89 | infringement under applicable copyright law, except executing it on a 90 | computer or modifying a private copy. Propagation includes copying, 91 | distribution (with or without modification), making available to the 92 | public, and in some countries other activities as well. 93 | 94 | To "convey" a work means any kind of propagation that enables other 95 | parties to make or receive copies. Mere interaction with a user 96 | through a computer network, with no transfer of a copy, is not 97 | conveying. 98 | 99 | An interactive user interface displays "Appropriate Legal Notices" to 100 | the extent that it includes a convenient and prominently visible 101 | feature that (1) displays an appropriate copyright notice, and (2) 102 | tells the user that there is no warranty for the work (except to the 103 | extent that warranties are provided), that licensees may convey the 104 | work under this License, and how to view a copy of this License. If 105 | the interface presents a list of user commands or options, such as a 106 | menu, a prominent item in the list meets this criterion. 107 | 108 | ### 1. Source Code. 109 | 110 | The "source code" for a work means the preferred form of the work for 111 | making modifications to it. "Object code" means any non-source form of 112 | a work. 113 | 114 | A "Standard Interface" means an interface that either is an official 115 | standard defined by a recognized standards body, or, in the case of 116 | interfaces specified for a particular programming language, one that 117 | is widely used among developers working in that language. 118 | 119 | The "System Libraries" of an executable work include anything, other 120 | than the work as a whole, that (a) is included in the normal form of 121 | packaging a Major Component, but which is not part of that Major 122 | Component, and (b) serves only to enable use of the work with that 123 | Major Component, or to implement a Standard Interface for which an 124 | implementation is available to the public in source code form. A 125 | "Major Component", in this context, means a major essential component 126 | (kernel, window system, and so on) of the specific operating system 127 | (if any) on which the executable work runs, or a compiler used to 128 | produce the work, or an object code interpreter used to run it. 129 | 130 | The "Corresponding Source" for a work in object code form means all 131 | the source code needed to generate, install, and (for an executable 132 | work) run the object code and to modify the work, including scripts to 133 | control those activities. However, it does not include the work's 134 | System Libraries, or general-purpose tools or generally available free 135 | programs which are used unmodified in performing those activities but 136 | which are not part of the work. For example, Corresponding Source 137 | includes interface definition files associated with source files for 138 | the work, and the source code for shared libraries and dynamically 139 | linked subprograms that the work is specifically designed to require, 140 | such as by intimate data communication or control flow between those 141 | subprograms and other parts of the work. 142 | 143 | The Corresponding Source need not include anything that users can 144 | regenerate automatically from other parts of the Corresponding Source. 145 | 146 | The Corresponding Source for a work in source code form is that same 147 | work. 148 | 149 | ### 2. Basic Permissions. 150 | 151 | All rights granted under this License are granted for the term of 152 | copyright on the Program, and are irrevocable provided the stated 153 | conditions are met. This License explicitly affirms your unlimited 154 | permission to run the unmodified Program. The output from running a 155 | covered work is covered by this License only if the output, given its 156 | content, constitutes a covered work. This License acknowledges your 157 | rights of fair use or other equivalent, as provided by copyright law. 158 | 159 | You may make, run and propagate covered works that you do not convey, 160 | without conditions so long as your license otherwise remains in force. 161 | You may convey covered works to others for the sole purpose of having 162 | them make modifications exclusively for you, or provide you with 163 | facilities for running those works, provided that you comply with the 164 | terms of this License in conveying all material for which you do not 165 | control copyright. Those thus making or running the covered works for 166 | you must do so exclusively on your behalf, under your direction and 167 | control, on terms that prohibit them from making any copies of your 168 | copyrighted material outside their relationship with you. 169 | 170 | Conveying under any other circumstances is permitted solely under the 171 | conditions stated below. Sublicensing is not allowed; section 10 makes 172 | it unnecessary. 173 | 174 | ### 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 175 | 176 | No covered work shall be deemed part of an effective technological 177 | measure under any applicable law fulfilling obligations under article 178 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 179 | similar laws prohibiting or restricting circumvention of such 180 | measures. 181 | 182 | When you convey a covered work, you waive any legal power to forbid 183 | circumvention of technological measures to the extent such 184 | circumvention is effected by exercising rights under this License with 185 | respect to the covered work, and you disclaim any intention to limit 186 | operation or modification of the work as a means of enforcing, against 187 | the work's users, your or third parties' legal rights to forbid 188 | circumvention of technological measures. 189 | 190 | ### 4. Conveying Verbatim Copies. 191 | 192 | You may convey verbatim copies of the Program's source code as you 193 | receive it, in any medium, provided that you conspicuously and 194 | appropriately publish on each copy an appropriate copyright notice; 195 | keep intact all notices stating that this License and any 196 | non-permissive terms added in accord with section 7 apply to the code; 197 | keep intact all notices of the absence of any warranty; and give all 198 | recipients a copy of this License along with the Program. 199 | 200 | You may charge any price or no price for each copy that you convey, 201 | and you may offer support or warranty protection for a fee. 202 | 203 | ### 5. Conveying Modified Source Versions. 204 | 205 | You may convey a work based on the Program, or the modifications to 206 | produce it from the Program, in the form of source code under the 207 | terms of section 4, provided that you also meet all of these 208 | conditions: 209 | 210 | - a) The work must carry prominent notices stating that you modified 211 | it, and giving a relevant date. 212 | - b) The work must carry prominent notices stating that it is 213 | released under this License and any conditions added under 214 | section 7. This requirement modifies the requirement in section 4 215 | to "keep intact all notices". 216 | - c) You must license the entire work, as a whole, under this 217 | License to anyone who comes into possession of a copy. This 218 | License will therefore apply, along with any applicable section 7 219 | additional terms, to the whole of the work, and all its parts, 220 | regardless of how they are packaged. This License gives no 221 | permission to license the work in any other way, but it does not 222 | invalidate such permission if you have separately received it. 223 | - d) If the work has interactive user interfaces, each must display 224 | Appropriate Legal Notices; however, if the Program has interactive 225 | interfaces that do not display Appropriate Legal Notices, your 226 | work need not make them do so. 227 | 228 | A compilation of a covered work with other separate and independent 229 | works, which are not by their nature extensions of the covered work, 230 | and which are not combined with it such as to form a larger program, 231 | in or on a volume of a storage or distribution medium, is called an 232 | "aggregate" if the compilation and its resulting copyright are not 233 | used to limit the access or legal rights of the compilation's users 234 | beyond what the individual works permit. Inclusion of a covered work 235 | in an aggregate does not cause this License to apply to the other 236 | parts of the aggregate. 237 | 238 | ### 6. Conveying Non-Source Forms. 239 | 240 | You may convey a covered work in object code form under the terms of 241 | sections 4 and 5, provided that you also convey the machine-readable 242 | Corresponding Source under the terms of this License, in one of these 243 | ways: 244 | 245 | - a) Convey the object code in, or embodied in, a physical product 246 | (including a physical distribution medium), accompanied by the 247 | Corresponding Source fixed on a durable physical medium 248 | customarily used for software interchange. 249 | - b) Convey the object code in, or embodied in, a physical product 250 | (including a physical distribution medium), accompanied by a 251 | written offer, valid for at least three years and valid for as 252 | long as you offer spare parts or customer support for that product 253 | model, to give anyone who possesses the object code either (1) a 254 | copy of the Corresponding Source for all the software in the 255 | product that is covered by this License, on a durable physical 256 | medium customarily used for software interchange, for a price no 257 | more than your reasonable cost of physically performing this 258 | conveying of source, or (2) access to copy the Corresponding 259 | Source from a network server at no charge. 260 | - c) Convey individual copies of the object code with a copy of the 261 | written offer to provide the Corresponding Source. This 262 | alternative is allowed only occasionally and noncommercially, and 263 | only if you received the object code with such an offer, in accord 264 | with subsection 6b. 265 | - d) Convey the object code by offering access from a designated 266 | place (gratis or for a charge), and offer equivalent access to the 267 | Corresponding Source in the same way through the same place at no 268 | further charge. You need not require recipients to copy the 269 | Corresponding Source along with the object code. If the place to 270 | copy the object code is a network server, the Corresponding Source 271 | may be on a different server (operated by you or a third party) 272 | that supports equivalent copying facilities, provided you maintain 273 | clear directions next to the object code saying where to find the 274 | Corresponding Source. Regardless of what server hosts the 275 | Corresponding Source, you remain obligated to ensure that it is 276 | available for as long as needed to satisfy these requirements. 277 | - e) Convey the object code using peer-to-peer transmission, 278 | provided you inform other peers where the object code and 279 | Corresponding Source of the work are being offered to the general 280 | public at no charge under subsection 6d. 281 | 282 | A separable portion of the object code, whose source code is excluded 283 | from the Corresponding Source as a System Library, need not be 284 | included in conveying the object code work. 285 | 286 | A "User Product" is either (1) a "consumer product", which means any 287 | tangible personal property which is normally used for personal, 288 | family, or household purposes, or (2) anything designed or sold for 289 | incorporation into a dwelling. In determining whether a product is a 290 | consumer product, doubtful cases shall be resolved in favor of 291 | coverage. For a particular product received by a particular user, 292 | "normally used" refers to a typical or common use of that class of 293 | product, regardless of the status of the particular user or of the way 294 | in which the particular user actually uses, or expects or is expected 295 | to use, the product. A product is a consumer product regardless of 296 | whether the product has substantial commercial, industrial or 297 | non-consumer uses, unless such uses represent the only significant 298 | mode of use of the product. 299 | 300 | "Installation Information" for a User Product means any methods, 301 | procedures, authorization keys, or other information required to 302 | install and execute modified versions of a covered work in that User 303 | Product from a modified version of its Corresponding Source. The 304 | information must suffice to ensure that the continued functioning of 305 | the modified object code is in no case prevented or interfered with 306 | solely because modification has been made. 307 | 308 | If you convey an object code work under this section in, or with, or 309 | specifically for use in, a User Product, and the conveying occurs as 310 | part of a transaction in which the right of possession and use of the 311 | User Product is transferred to the recipient in perpetuity or for a 312 | fixed term (regardless of how the transaction is characterized), the 313 | Corresponding Source conveyed under this section must be accompanied 314 | by the Installation Information. But this requirement does not apply 315 | if neither you nor any third party retains the ability to install 316 | modified object code on the User Product (for example, the work has 317 | been installed in ROM). 318 | 319 | The requirement to provide Installation Information does not include a 320 | requirement to continue to provide support service, warranty, or 321 | updates for a work that has been modified or installed by the 322 | recipient, or for the User Product in which it has been modified or 323 | installed. Access to a network may be denied when the modification 324 | itself materially and adversely affects the operation of the network 325 | or violates the rules and protocols for communication across the 326 | network. 327 | 328 | Corresponding Source conveyed, and Installation Information provided, 329 | in accord with this section must be in a format that is publicly 330 | documented (and with an implementation available to the public in 331 | source code form), and must require no special password or key for 332 | unpacking, reading or copying. 333 | 334 | ### 7. Additional Terms. 335 | 336 | "Additional permissions" are terms that supplement the terms of this 337 | License by making exceptions from one or more of its conditions. 338 | Additional permissions that are applicable to the entire Program shall 339 | be treated as though they were included in this License, to the extent 340 | that they are valid under applicable law. If additional permissions 341 | apply only to part of the Program, that part may be used separately 342 | under those permissions, but the entire Program remains governed by 343 | this License without regard to the additional permissions. 344 | 345 | When you convey a copy of a covered work, you may at your option 346 | remove any additional permissions from that copy, or from any part of 347 | it. (Additional permissions may be written to require their own 348 | removal in certain cases when you modify the work.) You may place 349 | additional permissions on material, added by you to a covered work, 350 | for which you have or can give appropriate copyright permission. 351 | 352 | Notwithstanding any other provision of this License, for material you 353 | add to a covered work, you may (if authorized by the copyright holders 354 | of that material) supplement the terms of this License with terms: 355 | 356 | - a) Disclaiming warranty or limiting liability differently from the 357 | terms of sections 15 and 16 of this License; or 358 | - b) Requiring preservation of specified reasonable legal notices or 359 | author attributions in that material or in the Appropriate Legal 360 | Notices displayed by works containing it; or 361 | - c) Prohibiting misrepresentation of the origin of that material, 362 | or requiring that modified versions of such material be marked in 363 | reasonable ways as different from the original version; or 364 | - d) Limiting the use for publicity purposes of names of licensors 365 | or authors of the material; or 366 | - e) Declining to grant rights under trademark law for use of some 367 | trade names, trademarks, or service marks; or 368 | - f) Requiring indemnification of licensors and authors of that 369 | material by anyone who conveys the material (or modified versions 370 | of it) with contractual assumptions of liability to the recipient, 371 | for any liability that these contractual assumptions directly 372 | impose on those licensors and authors. 373 | 374 | All other non-permissive additional terms are considered "further 375 | restrictions" within the meaning of section 10. If the Program as you 376 | received it, or any part of it, contains a notice stating that it is 377 | governed by this License along with a term that is a further 378 | restriction, you may remove that term. If a license document contains 379 | a further restriction but permits relicensing or conveying under this 380 | License, you may add to a covered work material governed by the terms 381 | of that license document, provided that the further restriction does 382 | not survive such relicensing or conveying. 383 | 384 | If you add terms to a covered work in accord with this section, you 385 | must place, in the relevant source files, a statement of the 386 | additional terms that apply to those files, or a notice indicating 387 | where to find the applicable terms. 388 | 389 | Additional terms, permissive or non-permissive, may be stated in the 390 | form of a separately written license, or stated as exceptions; the 391 | above requirements apply either way. 392 | 393 | ### 8. Termination. 394 | 395 | You may not propagate or modify a covered work except as expressly 396 | provided under this License. Any attempt otherwise to propagate or 397 | modify it is void, and will automatically terminate your rights under 398 | this License (including any patent licenses granted under the third 399 | paragraph of section 11). 400 | 401 | However, if you cease all violation of this License, then your license 402 | from a particular copyright holder is reinstated (a) provisionally, 403 | unless and until the copyright holder explicitly and finally 404 | terminates your license, and (b) permanently, if the copyright holder 405 | fails to notify you of the violation by some reasonable means prior to 406 | 60 days after the cessation. 407 | 408 | Moreover, your license from a particular copyright holder is 409 | reinstated permanently if the copyright holder notifies you of the 410 | violation by some reasonable means, this is the first time you have 411 | received notice of violation of this License (for any work) from that 412 | copyright holder, and you cure the violation prior to 30 days after 413 | your receipt of the notice. 414 | 415 | Termination of your rights under this section does not terminate the 416 | licenses of parties who have received copies or rights from you under 417 | this License. If your rights have been terminated and not permanently 418 | reinstated, you do not qualify to receive new licenses for the same 419 | material under section 10. 420 | 421 | ### 9. Acceptance Not Required for Having Copies. 422 | 423 | You are not required to accept this License in order to receive or run 424 | a copy of the Program. Ancillary propagation of a covered work 425 | occurring solely as a consequence of using peer-to-peer transmission 426 | to receive a copy likewise does not require acceptance. However, 427 | nothing other than this License grants you permission to propagate or 428 | modify any covered work. These actions infringe copyright if you do 429 | not accept this License. Therefore, by modifying or propagating a 430 | covered work, you indicate your acceptance of this License to do so. 431 | 432 | ### 10. Automatic Licensing of Downstream Recipients. 433 | 434 | Each time you convey a covered work, the recipient automatically 435 | receives a license from the original licensors, to run, modify and 436 | propagate that work, subject to this License. You are not responsible 437 | for enforcing compliance by third parties with this License. 438 | 439 | An "entity transaction" is a transaction transferring control of an 440 | organization, or substantially all assets of one, or subdividing an 441 | organization, or merging organizations. If propagation of a covered 442 | work results from an entity transaction, each party to that 443 | transaction who receives a copy of the work also receives whatever 444 | licenses to the work the party's predecessor in interest had or could 445 | give under the previous paragraph, plus a right to possession of the 446 | Corresponding Source of the work from the predecessor in interest, if 447 | the predecessor has it or can get it with reasonable efforts. 448 | 449 | You may not impose any further restrictions on the exercise of the 450 | rights granted or affirmed under this License. For example, you may 451 | not impose a license fee, royalty, or other charge for exercise of 452 | rights granted under this License, and you may not initiate litigation 453 | (including a cross-claim or counterclaim in a lawsuit) alleging that 454 | any patent claim is infringed by making, using, selling, offering for 455 | sale, or importing the Program or any portion of it. 456 | 457 | ### 11. Patents. 458 | 459 | A "contributor" is a copyright holder who authorizes use under this 460 | License of the Program or a work on which the Program is based. The 461 | work thus licensed is called the contributor's "contributor version". 462 | 463 | A contributor's "essential patent claims" are all patent claims owned 464 | or controlled by the contributor, whether already acquired or 465 | hereafter acquired, that would be infringed by some manner, permitted 466 | by this License, of making, using, or selling its contributor version, 467 | but do not include claims that would be infringed only as a 468 | consequence of further modification of the contributor version. For 469 | purposes of this definition, "control" includes the right to grant 470 | patent sublicenses in a manner consistent with the requirements of 471 | this License. 472 | 473 | Each contributor grants you a non-exclusive, worldwide, royalty-free 474 | patent license under the contributor's essential patent claims, to 475 | make, use, sell, offer for sale, import and otherwise run, modify and 476 | propagate the contents of its contributor version. 477 | 478 | In the following three paragraphs, a "patent license" is any express 479 | agreement or commitment, however denominated, not to enforce a patent 480 | (such as an express permission to practice a patent or covenant not to 481 | sue for patent infringement). To "grant" such a patent license to a 482 | party means to make such an agreement or commitment not to enforce a 483 | patent against the party. 484 | 485 | If you convey a covered work, knowingly relying on a patent license, 486 | and the Corresponding Source of the work is not available for anyone 487 | to copy, free of charge and under the terms of this License, through a 488 | publicly available network server or other readily accessible means, 489 | then you must either (1) cause the Corresponding Source to be so 490 | available, or (2) arrange to deprive yourself of the benefit of the 491 | patent license for this particular work, or (3) arrange, in a manner 492 | consistent with the requirements of this License, to extend the patent 493 | license to downstream recipients. "Knowingly relying" means you have 494 | actual knowledge that, but for the patent license, your conveying the 495 | covered work in a country, or your recipient's use of the covered work 496 | in a country, would infringe one or more identifiable patents in that 497 | country that you have reason to believe are valid. 498 | 499 | If, pursuant to or in connection with a single transaction or 500 | arrangement, you convey, or propagate by procuring conveyance of, a 501 | covered work, and grant a patent license to some of the parties 502 | receiving the covered work authorizing them to use, propagate, modify 503 | or convey a specific copy of the covered work, then the patent license 504 | you grant is automatically extended to all recipients of the covered 505 | work and works based on it. 506 | 507 | A patent license is "discriminatory" if it does not include within the 508 | scope of its coverage, prohibits the exercise of, or is conditioned on 509 | the non-exercise of one or more of the rights that are specifically 510 | granted under this License. You may not convey a covered work if you 511 | are a party to an arrangement with a third party that is in the 512 | business of distributing software, under which you make payment to the 513 | third party based on the extent of your activity of conveying the 514 | work, and under which the third party grants, to any of the parties 515 | who would receive the covered work from you, a discriminatory patent 516 | license (a) in connection with copies of the covered work conveyed by 517 | you (or copies made from those copies), or (b) primarily for and in 518 | connection with specific products or compilations that contain the 519 | covered work, unless you entered into that arrangement, or that patent 520 | license was granted, prior to 28 March 2007. 521 | 522 | Nothing in this License shall be construed as excluding or limiting 523 | any implied license or other defenses to infringement that may 524 | otherwise be available to you under applicable patent law. 525 | 526 | ### 12. No Surrender of Others' Freedom. 527 | 528 | If conditions are imposed on you (whether by court order, agreement or 529 | otherwise) that contradict the conditions of this License, they do not 530 | excuse you from the conditions of this License. If you cannot convey a 531 | covered work so as to satisfy simultaneously your obligations under 532 | this License and any other pertinent obligations, then as a 533 | consequence you may not convey it at all. For example, if you agree to 534 | terms that obligate you to collect a royalty for further conveying 535 | from those to whom you convey the Program, the only way you could 536 | satisfy both those terms and this License would be to refrain entirely 537 | from conveying the Program. 538 | 539 | ### 13. Remote Network Interaction; Use with the GNU General Public License. 540 | 541 | Notwithstanding any other provision of this License, if you modify the 542 | Program, your modified version must prominently offer all users 543 | interacting with it remotely through a computer network (if your 544 | version supports such interaction) an opportunity to receive the 545 | Corresponding Source of your version by providing access to the 546 | Corresponding Source from a network server at no charge, through some 547 | standard or customary means of facilitating copying of software. This 548 | Corresponding Source shall include the Corresponding Source for any 549 | work covered by version 3 of the GNU General Public License that is 550 | incorporated pursuant to the following paragraph. 551 | 552 | Notwithstanding any other provision of this License, you have 553 | permission to link or combine any covered work with a work licensed 554 | under version 3 of the GNU General Public License into a single 555 | combined work, and to convey the resulting work. The terms of this 556 | License will continue to apply to the part which is the covered work, 557 | but the work with which it is combined will remain governed by version 558 | 3 of the GNU General Public License. 559 | 560 | ### 14. Revised Versions of this License. 561 | 562 | The Free Software Foundation may publish revised and/or new versions 563 | of the GNU Affero General Public License from time to time. Such new 564 | versions will be similar in spirit to the present version, but may 565 | differ in detail to address new problems or concerns. 566 | 567 | Each version is given a distinguishing version number. If the Program 568 | specifies that a certain numbered version of the GNU Affero General 569 | Public License "or any later version" applies to it, you have the 570 | option of following the terms and conditions either of that numbered 571 | version or of any later version published by the Free Software 572 | Foundation. If the Program does not specify a version number of the 573 | GNU Affero General Public License, you may choose any version ever 574 | published by the Free Software Foundation. 575 | 576 | If the Program specifies that a proxy can decide which future versions 577 | of the GNU Affero General Public License can be used, that proxy's 578 | public statement of acceptance of a version permanently authorizes you 579 | to choose that version for the Program. 580 | 581 | Later license versions may give you additional or different 582 | permissions. However, no additional obligations are imposed on any 583 | author or copyright holder as a result of your choosing to follow a 584 | later version. 585 | 586 | ### 15. Disclaimer of Warranty. 587 | 588 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 589 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 590 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT 591 | WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT 592 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 593 | A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND 594 | PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE 595 | DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR 596 | CORRECTION. 597 | 598 | ### 16. Limitation of Liability. 599 | 600 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 601 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR 602 | CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 603 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES 604 | ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT 605 | NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR 606 | LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM 607 | TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER 608 | PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 609 | 610 | ### 17. Interpretation of Sections 15 and 16. 611 | 612 | If the disclaimer of warranty and limitation of liability provided 613 | above cannot be given local legal effect according to their terms, 614 | reviewing courts shall apply local law that most closely approximates 615 | an absolute waiver of all civil liability in connection with the 616 | Program, unless a warranty or assumption of liability accompanies a 617 | copy of the Program in return for a fee. 618 | 619 | END OF TERMS AND CONDITIONS 620 | 621 | ## How to Apply These Terms to Your New Programs 622 | 623 | If you develop a new program, and you want it to be of the greatest 624 | possible use to the public, the best way to achieve this is to make it 625 | free software which everyone can redistribute and change under these 626 | terms. 627 | 628 | To do so, attach the following notices to the program. It is safest to 629 | attach them to the start of each source file to most effectively state 630 | the exclusion of warranty; and each file should have at least the 631 | "copyright" line and a pointer to where the full notice is found. 632 | 633 | 634 | Copyright (C) 635 | 636 | This program is free software: you can redistribute it and/or modify 637 | it under the terms of the GNU Affero General Public License as 638 | published by the Free Software Foundation, either version 3 of the 639 | License, or (at your option) any later version. 640 | 641 | This program is distributed in the hope that it will be useful, 642 | but WITHOUT ANY WARRANTY; without even the implied warranty of 643 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 644 | GNU Affero General Public License for more details. 645 | 646 | You should have received a copy of the GNU Affero General Public License 647 | along with this program. If not, see . 648 | 649 | Also add information on how to contact you by electronic and paper 650 | mail. 651 | 652 | If your software can interact with users remotely through a computer 653 | network, you should also make sure that it provides a way for users to 654 | get its source. For example, if your program is a web application, its 655 | interface could display a "Source" link that leads users to an archive 656 | of the code. There are many ways you could offer source, and different 657 | solutions will be better for different programs; see section 13 for 658 | the specific requirements. 659 | 660 | You should also get your employer (if you work as a programmer) or 661 | school, if any, to sign a "copyright disclaimer" for the program, if 662 | necessary. For more information on this, and how to apply and follow 663 | the GNU AGPL, see . -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 | initMAX Logo 6 |

7 | 8 | Honesty, diligence and MAXimum knowledge of our products is our standard. 9 | 10 |

11 |

12 | 13 | Static Badge 14 |   15 | 16 | Static Badge 17 |   18 | 19 | Static Badge 20 |   21 | 22 | Static Badge 23 |   24 | 25 | Static Badge 26 |   27 | 28 | Static Badge 29 |   30 | 31 | Static Badge 32 | 33 |

34 |

35 | Zabbix premium partner    36 | Zabbix certified trainer 37 |

38 |
39 |
40 |
41 | 42 | --- 43 | --- 44 | 45 |
46 |

47 | ChatGPT 48 |

49 |

50 | The ChatGPT widget integrates AI capabilities into your Zabbix dashboard, allowing interaction with OpenAI models directly from the widget. 51 |

52 |
53 | Static Badge 54 | Static Badge 55 |

56 | Requirements • 57 | Description 58 | Editions • 59 | Installation 60 |

61 |
62 | 63 |
64 |
65 |
66 | 67 | 68 | 69 | 70 | ## Requirements 71 | 72 | - Zabbix 7.0 73 | - You need to create OpenAI API token https://platform.openai.com/docs/introduction/overview 74 | 75 | 76 |
77 | 78 | ## Description 79 | The ChatGPT widget integrates AI capabilities into your Zabbix dashboard, allowing interaction with OpenAI models directly from the widget. 80 | 81 |
82 |
83 | 84 |
85 | 86 | 87 |
88 |
89 | 90 | ## Editions 91 | 92 |
93 | 94 | | Function | FREE | PRO | 95 | |--------------------------------------------------|:------:|:----------:| 96 | | Set own OpenAI token | ✅ | ✅ | 97 | | Choose ChatGPT model | ❌ | ✅ | 98 | | Advanced configuration parameters for prompt responses | ❌ | ✅ | 99 | | Button for stopping response generation | ❌ | ✅ | 100 | | Copy button within markdown section | ❌ | ✅ | 101 | | Customizable field for API endpoints | ❌ | ✅ | 102 | 103 |

104 | Get the PRO version at info@initmax.com 105 |

106 |
107 | 108 | 109 | 110 | 111 | ## Installation 112 | - Connect to your Zabbix frontend server (perform on all frontend nodes) 113 | 114 | - Navigate to the `ui/modules/` directory (`ui` is typically located at `/usr/share/zabbix/`) 115 | ```sh 116 | cd /usr/share/zabbix/modules/ 117 | ``` 118 | 119 | - Clone repository on your server 120 | ```sh 121 | git clone https://git.initmax.cz/initMAX-Public/zabbix-chatgpt-widget.git 122 | ``` 123 | 124 | - Change the owner of directory to your web user with `chown` 125 | - default OS users 126 | - nginx 127 | ```sh 128 | chown nginx:nginx ./zabbix-chatgpt-widget 129 | ``` 130 | - apache (RHEL) 131 | ```sh 132 | chown apache:apache ./zabbix-chatgpt-widget 133 | ``` 134 | - apache (DEB) 135 | ```sh 136 | chown www-data:www-data ./zabbix-chatgpt-widget 137 | ``` 138 | 139 | - Go to Zabbix frontend menu -> Administration -> General -> Modules 140 |
141 | 142 |
143 | 144 | - Use the Scan directory button on the top 145 |
146 | 147 |
148 | 149 | - Enable the newly discovered module 150 |
151 | 152 |
153 | 154 | - Done 155 |
156 | 157 |
158 | 159 | - Use it and enjoy! 160 | 161 | 162 | 163 | 164 |
165 |
166 | 167 | --- 168 | --- 169 |
170 |

171 | 172 | Static Badge 173 | 174 | 175 | Static Badge 176 | 177 | 178 | Static Badge 179 | 180 |
181 | 182 | Static Badge 183 |   184 | 185 | Static Badge 186 |   187 | 188 | Static Badge 189 |   190 | 191 | Static Badge 192 |   193 | 194 | Static Badge 195 |   196 | 197 | Static Badge 198 | 199 |


200 | 201 | 202 | 203 |

204 |
-------------------------------------------------------------------------------- /Widget.php: -------------------------------------------------------------------------------- 1 | setResponse(new CControllerResponseData([ 31 | 'name' => $this->getInput('name', $this->widget->getName()), 32 | 'fields_values' => $this->fields_values, 33 | 'user' => [ 34 | 'debug_mode' => $this->getDebugMode() 35 | ] 36 | ])); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /assets/css/form.css: -------------------------------------------------------------------------------- 1 | .initmax-free:before { 2 | content: ''; 3 | 4 | background: url('../img/initmax-free.svg'); 5 | background-position: center; 6 | background-size: contain; 7 | background-repeat: no-repeat; 8 | background-clip: padding-box; 9 | 10 | display: flex; 11 | 12 | height: 4rem; 13 | 14 | margin: 2rem 0; 15 | } 16 | -------------------------------------------------------------------------------- /assets/css/widget.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | src: url('../font/rubik-regular.ttf') format('truetype'), 3 | url('../font/rubik-regular.woff2') format('woff2'), 4 | url('../font/rubik-regular.woff') format('woff'); 5 | 6 | font-family: 'Rubik'; 7 | font-weight: 400; 8 | font-style: normal; 9 | } 10 | 11 | .chat-container { 12 | height: 100%; 13 | 14 | display: flex; 15 | flex-direction: column; 16 | gap: 0.5rem; 17 | 18 | background-image: url('../img/background.png'); 19 | background-size: cover; 20 | background-repeat: no-repeat; 21 | background-position: center; 22 | 23 | font-size: 1.25rem; 24 | font-family: 'Rubik'; 25 | color: white; 26 | 27 | .chat-header { 28 | padding: 1rem 1rem 0 1rem; 29 | } 30 | 31 | .chat-log { 32 | flex: 1; 33 | 34 | padding: 0 1rem; 35 | 36 | overflow-y: auto; 37 | scrollbar-color: #007 transparent; 38 | scrollbar-width: thin; 39 | 40 | > * { 41 | margin-bottom: 1.5rem; 42 | } 43 | 44 | > *:last-child { 45 | margin-bottom: 0; 46 | } 47 | } 48 | 49 | .chat-form { 50 | display: flex; 51 | padding: 1rem; 52 | 53 | .chat-form-button, 54 | .chat-form-button-stop { 55 | height: 3rem; 56 | 57 | border-radius: 0 1rem 1rem 0; 58 | 59 | border-width: 1px; 60 | border-style: solid; 61 | border-color: #1F65F4; 62 | border-left: none; 63 | 64 | background-color: #FFFFFF25 !important; 65 | 66 | font-size: 2rem; 67 | 68 | outline: 0; 69 | } 70 | 71 | .chat-form-button:active, 72 | .chat-form-button-stop:active { 73 | outline: 0; 74 | } 75 | 76 | .chat-form-button:hover, 77 | .chat-form-button-stop:hover { 78 | color: #1F65F4; 79 | } 80 | 81 | .chat-form-button--hidden, 82 | .chat-form-button-stop--hidden { 83 | display: none; 84 | } 85 | } 86 | } 87 | 88 | 89 | 90 | .chat-form-message { 91 | height: 3rem; 92 | 93 | flex: 1; 94 | 95 | border-width: 1px !important; 96 | border-style: solid !important; 97 | border-color: #1F65F4 !important; 98 | border-right: none !important; 99 | 100 | border-radius: 1rem 0 0 1rem; 101 | 102 | padding: 0rem 1rem !important; 103 | 104 | background-color: #FFFFFF25 !important; 105 | 106 | font-family: 'Rubik'; 107 | color: white !important; 108 | } 109 | 110 | 111 | 112 | .chat-form-message:placeholder-shown ~ .chat-form-button { 113 | pointer-events: none; 114 | color: #FFFFFF50; 115 | } 116 | 117 | 118 | .chat-log-message { 119 | display: flex; 120 | gap: 1rem; 121 | } 122 | 123 | .chat-log-message-bot { 124 | 125 | } 126 | 127 | .chat-log-message-user { 128 | justify-content: flex-end; 129 | } 130 | 131 | .chat-log-message-author { 132 | width: 2.5rem; 133 | height: 2.5rem; 134 | min-width: 2.5rem; 135 | min-height: 2.5rem; 136 | 137 | border-style: solid; 138 | border-width: 1px; 139 | border-color: #1F65F4; 140 | border-radius: 50%; 141 | 142 | align-self: flex-end; 143 | 144 | background-position: center; 145 | background-repeat: no-repeat; 146 | background-color: white; 147 | } 148 | 149 | .chat-log-message-author-bot { 150 | background-image: url('../img/avatar-chatgpt.png'); 151 | background-size: 75%; 152 | } 153 | 154 | .chat-log-message-author-user { 155 | order: 1; 156 | 157 | background-image: url('../img/avatar-initmax.png'); 158 | background-size: 65%; 159 | } 160 | 161 | .chat-log-message-text { 162 | min-width: 60px; 163 | max-width: 75%; 164 | 165 | display: flex; 166 | justify-content: center; 167 | flex-direction: column; 168 | 169 | text-align: justify; 170 | 171 | border-color: #1F65F4; 172 | border-style: solid; 173 | border-width: 1px; 174 | border-radius: 1rem; 175 | 176 | padding: 0.5rem 1rem; 177 | 178 | box-sizing: border-box; 179 | line-height: 150%; 180 | 181 | p { 182 | margin: 0; 183 | } 184 | } 185 | 186 | .chat-log-message-text-user { 187 | background-color: #1F65F4; 188 | justify-content: flex-end; 189 | } 190 | 191 | .dot-flashing { 192 | /*top: 5px;*/ 193 | left: 10px; 194 | position: relative; 195 | width: 5px; 196 | height: 5px; 197 | border-radius: 50%; 198 | background-color: #9880ff; 199 | color: #9880ff; 200 | animation: dot-flashing 1s infinite linear alternate; 201 | animation-delay: 0.5s; 202 | } 203 | 204 | .dot-flashing::before, .dot-flashing::after { 205 | content: ""; 206 | display: inline-block; 207 | position: absolute; 208 | top: 0; 209 | } 210 | 211 | .dot-flashing::before { 212 | left: -10px; 213 | width: 5px; 214 | height: 5px; 215 | border-radius: 50%; 216 | background-color: #9880ff; 217 | color: #9880ff; 218 | animation: dot-flashing 1s infinite alternate; 219 | animation-delay: 0s; 220 | } 221 | .dot-flashing::after { 222 | left: 10px; 223 | width: 5px; 224 | height: 5px; 225 | border-radius: 50%; 226 | background-color: #9880ff; 227 | color: #9880ff; 228 | animation: dot-flashing 1s infinite alternate; 229 | animation-delay: 1s; 230 | } 231 | 232 | @keyframes dot-flashing { 233 | 0% { 234 | background-color: #9880ff; 235 | } 236 | 50%, 100% { 237 | background-color: rgba(152, 128, 255, 0.2); 238 | } 239 | } 240 | -------------------------------------------------------------------------------- /assets/font/rubik-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/initMAX/Zabbix-UI-Widgets-ChatGPT/78eff010c95bbbb077f1661098d91d97b75ccabc/assets/font/rubik-regular.ttf -------------------------------------------------------------------------------- /assets/font/rubik-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/initMAX/Zabbix-UI-Widgets-ChatGPT/78eff010c95bbbb077f1661098d91d97b75ccabc/assets/font/rubik-regular.woff -------------------------------------------------------------------------------- /assets/font/rubik-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/initMAX/Zabbix-UI-Widgets-ChatGPT/78eff010c95bbbb077f1661098d91d97b75ccabc/assets/font/rubik-regular.woff2 -------------------------------------------------------------------------------- /assets/img/avatar-chatgpt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/initMAX/Zabbix-UI-Widgets-ChatGPT/78eff010c95bbbb077f1661098d91d97b75ccabc/assets/img/avatar-chatgpt.png -------------------------------------------------------------------------------- /assets/img/avatar-initmax.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/initMAX/Zabbix-UI-Widgets-ChatGPT/78eff010c95bbbb077f1661098d91d97b75ccabc/assets/img/avatar-initmax.png -------------------------------------------------------------------------------- /assets/img/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/initMAX/Zabbix-UI-Widgets-ChatGPT/78eff010c95bbbb077f1661098d91d97b75ccabc/assets/img/background.png -------------------------------------------------------------------------------- /assets/img/initmax-free.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/img/initmax.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /assets/js/class.widget.js: -------------------------------------------------------------------------------- 1 | /* 2 | ** initMAX 3 | ** Copyright (C) 2021-2022 initMAX s.r.o. 4 | ** 5 | ** This program is free software; you can redistribute it and/or modify 6 | ** it under the terms of the GNU General Public License as published by 7 | ** the Free Software Foundation; either version 3 of the License, or 8 | ** (at your option) any later version. 9 | ** 10 | ** This program is distributed in the hope that it will be useful, 11 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | ** GNU General Public License for more details. 14 | ** 15 | ** You should have received a copy of the GNU General Public License 16 | ** along with this program; if not, write to the Free Software 17 | ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | **/ 19 | 20 | class CWidgetOpenAI extends CWidget { 21 | apiToken = this._fields.token; 22 | apiEndpoint = this._fields.endpoint; 23 | stream = true; 24 | abort = false; 25 | 26 | setContents(response) { 27 | super.setContents(response); 28 | 29 | this.sendButton = this._body.querySelector('[name=send-button]'); 30 | this.stopButton = this._body.querySelector('[name=stop-button]'); 31 | this.userInput = this._body.querySelector('.chat-form-message'); 32 | this.chatLog = this._body.querySelector('.chat-log'); 33 | 34 | this.userInput.addEventListener('keydown', e => { 35 | if (e.code == 'Enter' || e.code == 'NumpadEnter') { 36 | this.sendMessage(); 37 | } 38 | }); 39 | this.sendButton.addEventListener('click', this.sendMessage.bind(this)); 40 | this.stopButton.addEventListener('click', this.stopStream.bind(this)); 41 | } 42 | 43 | async sendMessage() { 44 | const question = this.userInput.value; 45 | this.userInput.value = ''; 46 | 47 | if (!question) { 48 | return; 49 | } 50 | 51 | this.hideSendButton(); 52 | this.showStopButton(); 53 | 54 | this.stopController = new AbortController(); 55 | 56 | const questionElement = this.createMessage('user'); 57 | questionElement.innerHTML = question; 58 | 59 | const answerElement = this.createMessage('bot'); 60 | 61 | const request = await fetch(this.apiEndpoint, { 62 | method: 'POST', 63 | headers: { 64 | 'Content-Type': 'application/json', 65 | 'Authorization': `Bearer ${this.apiToken}` 66 | }, 67 | signal: this.stopController.signal, 68 | body: JSON.stringify({ 69 | model: 'gpt-3.5-turbo', 70 | messages: [ 71 | { 72 | role: 'user', 73 | content: question, 74 | }, 75 | ], 76 | stream: this.stream, 77 | }) 78 | }); 79 | 80 | if (this.stream) { 81 | await this.streamResponse(request, answerElement); 82 | } 83 | else { 84 | await this.response(request, answerElement); 85 | } 86 | 87 | this.showSendButton(); 88 | this.hideStopButton(); 89 | } 90 | 91 | stopStream() { 92 | if (this.stream) { 93 | this.stopController.abort(); 94 | } 95 | 96 | this.showSendButton(); 97 | this.hideStopButton(); 98 | } 99 | 100 | async streamResponse(request, answerElement) { 101 | const reader = request.body?.pipeThrough(new TextDecoderStream()).getReader(); 102 | 103 | let lastJsonLine = ''; 104 | let rawAnswer = ''; 105 | 106 | while (true) { 107 | const res = await reader?.read(); 108 | 109 | if (res?.done) { 110 | return; 111 | } 112 | 113 | if (!res?.value) { 114 | continue; 115 | } 116 | 117 | const jsonChunks = res.value.split('\n\n').filter(line => line.trim().length > 0); 118 | 119 | for (const chunk of jsonChunks) { 120 | lastJsonLine += chunk; 121 | if (lastJsonLine.startsWith('data:')) { 122 | lastJsonLine = lastJsonLine.slice('data:'.length); 123 | } 124 | 125 | try { 126 | const answer = JSON.parse(lastJsonLine); 127 | lastJsonLine = '' 128 | 129 | if (answer.choices[0].delta.finish_reason !== 'stop') { 130 | const reply = answer.choices[0].delta.content; 131 | 132 | for (let e = 0, len = reply.length; e < len; e++) { 133 | 134 | if (answerElement.querySelector('.dot-flashing')) { 135 | answerElement.querySelector('.dot-flashing').remove(); 136 | } 137 | 138 | rawAnswer += reply[e]; 139 | 140 | answerElement.innerHTML = marked.parse(rawAnswer); 141 | this.chatLog.scrollTop = this.chatLog.scrollHeight; 142 | } 143 | } 144 | } catch (e) {} 145 | } 146 | } 147 | } 148 | 149 | async response(request, answerElement) { 150 | const response = await request.json(); 151 | 152 | if (response.choices.length > 0) { 153 | answerElement.innerHTML = response.choices[0].message.content; 154 | this.chatLog.scrollTop = this.chatLog.scrollHeight; 155 | } 156 | } 157 | 158 | createMessage(sender) { 159 | if (!(sender === 'user' || sender === 'bot')) { 160 | return null; 161 | } 162 | 163 | const message = document.createElement('div'); 164 | message.classList.add('chat-log-message', `chat-log-message-${sender}`); 165 | 166 | message.insertAdjacentHTML( 167 | 'beforeend', 168 | `
169 |
` 170 | ); 171 | 172 | this.chatLog.appendChild(message); 173 | this.chatLog.scrollTop = this.chatLog.scrollHeight; 174 | 175 | return message.querySelector('.chat-log-message-text'); 176 | } 177 | 178 | hideSendButton() { 179 | if (this.abort) this.sendButton.classList.add('chat-form-button--hidden'); 180 | } 181 | 182 | showSendButton() { 183 | if (this.abort) this.sendButton.classList.remove('chat-form-button--hidden'); 184 | } 185 | 186 | hideStopButton() { 187 | if (this.abort) this.stopButton.classList.add('chat-form-button-stop--hidden'); 188 | } 189 | 190 | showStopButton() { 191 | if (this.abort) this.stopButton.classList.remove('chat-form-button-stop--hidden'); 192 | } 193 | 194 | hasPadding () { 195 | return false; 196 | } 197 | } 198 | -------------------------------------------------------------------------------- /assets/js/marked.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * marked v12.0.2 - a markdown parser 3 | * Copyright (c) 2011-2024, Christopher Jeffrey. (MIT Licensed) 4 | * https://github.com/markedjs/marked 5 | */ 6 | !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).marked={})}(this,(function(e){"use strict";function t(){return{async:!1,breaks:!1,extensions:null,gfm:!0,hooks:null,pedantic:!1,renderer:null,silent:!1,tokenizer:null,walkTokens:null}}function n(t){e.defaults=t}e.defaults={async:!1,breaks:!1,extensions:null,gfm:!0,hooks:null,pedantic:!1,renderer:null,silent:!1,tokenizer:null,walkTokens:null};const s=/[&<>"']/,r=new RegExp(s.source,"g"),i=/[<>"']|&(?!(#\d{1,7}|#[Xx][a-fA-F0-9]{1,6}|\w+);)/,l=new RegExp(i.source,"g"),o={"&":"&","<":"<",">":">",'"':""","'":"'"},a=e=>o[e];function c(e,t){if(t){if(s.test(e))return e.replace(r,a)}else if(i.test(e))return e.replace(l,a);return e}const h=/&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/gi;function p(e){return e.replace(h,((e,t)=>"colon"===(t=t.toLowerCase())?":":"#"===t.charAt(0)?"x"===t.charAt(1)?String.fromCharCode(parseInt(t.substring(2),16)):String.fromCharCode(+t.substring(1)):""))}const u=/(^|[^\[])\^/g;function k(e,t){let n="string"==typeof e?e:e.source;t=t||"";const s={replace:(e,t)=>{let r="string"==typeof t?t:t.source;return r=r.replace(u,"$1"),n=n.replace(e,r),s},getRegex:()=>new RegExp(n,t)};return s}function g(e){try{e=encodeURI(e).replace(/%25/g,"%")}catch(e){return null}return e}const f={exec:()=>null};function d(e,t){const n=e.replace(/\|/g,((e,t,n)=>{let s=!1,r=t;for(;--r>=0&&"\\"===n[r];)s=!s;return s?"|":" |"})).split(/ \|/);let s=0;if(n[0].trim()||n.shift(),n.length>0&&!n[n.length-1].trim()&&n.pop(),t)if(n.length>t)n.splice(t);else for(;n.length0)return{type:"space",raw:t[0]}}code(e){const t=this.rules.block.code.exec(e);if(t){const e=t[0].replace(/^ {1,4}/gm,"");return{type:"code",raw:t[0],codeBlockStyle:"indented",text:this.options.pedantic?e:x(e,"\n")}}}fences(e){const t=this.rules.block.fences.exec(e);if(t){const e=t[0],n=function(e,t){const n=e.match(/^(\s+)(?:```)/);if(null===n)return t;const s=n[1];return t.split("\n").map((e=>{const t=e.match(/^\s+/);if(null===t)return e;const[n]=t;return n.length>=s.length?e.slice(s.length):e})).join("\n")}(e,t[3]||"");return{type:"code",raw:e,lang:t[2]?t[2].trim().replace(this.rules.inline.anyPunctuation,"$1"):t[2],text:n}}}heading(e){const t=this.rules.block.heading.exec(e);if(t){let e=t[2].trim();if(/#$/.test(e)){const t=x(e,"#");this.options.pedantic?e=t.trim():t&&!/ $/.test(t)||(e=t.trim())}return{type:"heading",raw:t[0],depth:t[1].length,text:e,tokens:this.lexer.inline(e)}}}hr(e){const t=this.rules.block.hr.exec(e);if(t)return{type:"hr",raw:t[0]}}blockquote(e){const t=this.rules.block.blockquote.exec(e);if(t){let e=t[0].replace(/\n {0,3}((?:=+|-+) *)(?=\n|$)/g,"\n $1");e=x(e.replace(/^ *>[ \t]?/gm,""),"\n");const n=this.lexer.state.top;this.lexer.state.top=!0;const s=this.lexer.blockTokens(e);return this.lexer.state.top=n,{type:"blockquote",raw:t[0],tokens:s,text:e}}}list(e){let t=this.rules.block.list.exec(e);if(t){let n=t[1].trim();const s=n.length>1,r={type:"list",raw:"",ordered:s,start:s?+n.slice(0,-1):"",loose:!1,items:[]};n=s?`\\d{1,9}\\${n.slice(-1)}`:`\\${n}`,this.options.pedantic&&(n=s?n:"[*+-]");const i=new RegExp(`^( {0,3}${n})((?:[\t ][^\\n]*)?(?:\\n|$))`);let l="",o="",a=!1;for(;e;){let n=!1;if(!(t=i.exec(e)))break;if(this.rules.block.hr.test(e))break;l=t[0],e=e.substring(l.length);let s=t[2].split("\n",1)[0].replace(/^\t+/,(e=>" ".repeat(3*e.length))),c=e.split("\n",1)[0],h=0;this.options.pedantic?(h=2,o=s.trimStart()):(h=t[2].search(/[^ ]/),h=h>4?1:h,o=s.slice(h),h+=t[1].length);let p=!1;if(!s&&/^ *$/.test(c)&&(l+=c+"\n",e=e.substring(c.length+1),n=!0),!n){const t=new RegExp(`^ {0,${Math.min(3,h-1)}}(?:[*+-]|\\d{1,9}[.)])((?:[ \t][^\\n]*)?(?:\\n|$))`),n=new RegExp(`^ {0,${Math.min(3,h-1)}}((?:- *){3,}|(?:_ *){3,}|(?:\\* *){3,})(?:\\n+|$)`),r=new RegExp(`^ {0,${Math.min(3,h-1)}}(?:\`\`\`|~~~)`),i=new RegExp(`^ {0,${Math.min(3,h-1)}}#`);for(;e;){const a=e.split("\n",1)[0];if(c=a,this.options.pedantic&&(c=c.replace(/^ {1,4}(?=( {4})*[^ ])/g," ")),r.test(c))break;if(i.test(c))break;if(t.test(c))break;if(n.test(e))break;if(c.search(/[^ ]/)>=h||!c.trim())o+="\n"+c.slice(h);else{if(p)break;if(s.search(/[^ ]/)>=4)break;if(r.test(s))break;if(i.test(s))break;if(n.test(s))break;o+="\n"+c}p||c.trim()||(p=!0),l+=a+"\n",e=e.substring(a.length+1),s=c.slice(h)}}r.loose||(a?r.loose=!0:/\n *\n *$/.test(l)&&(a=!0));let u,k=null;this.options.gfm&&(k=/^\[[ xX]\] /.exec(o),k&&(u="[ ] "!==k[0],o=o.replace(/^\[[ xX]\] +/,""))),r.items.push({type:"list_item",raw:l,task:!!k,checked:u,loose:!1,text:o,tokens:[]}),r.raw+=l}r.items[r.items.length-1].raw=l.trimEnd(),r.items[r.items.length-1].text=o.trimEnd(),r.raw=r.raw.trimEnd();for(let e=0;e"space"===e.type)),n=t.length>0&&t.some((e=>/\n.*\n/.test(e.raw)));r.loose=n}if(r.loose)for(let e=0;e$/,"$1").replace(this.rules.inline.anyPunctuation,"$1"):"",s=t[3]?t[3].substring(1,t[3].length-1).replace(this.rules.inline.anyPunctuation,"$1"):t[3];return{type:"def",tag:e,raw:t[0],href:n,title:s}}}table(e){const t=this.rules.block.table.exec(e);if(!t)return;if(!/[:|]/.test(t[2]))return;const n=d(t[1]),s=t[2].replace(/^\||\| *$/g,"").split("|"),r=t[3]&&t[3].trim()?t[3].replace(/\n[ \t]*$/,"").split("\n"):[],i={type:"table",raw:t[0],header:[],align:[],rows:[]};if(n.length===s.length){for(const e of s)/^ *-+: *$/.test(e)?i.align.push("right"):/^ *:-+: *$/.test(e)?i.align.push("center"):/^ *:-+ *$/.test(e)?i.align.push("left"):i.align.push(null);for(const e of n)i.header.push({text:e,tokens:this.lexer.inline(e)});for(const e of r)i.rows.push(d(e,i.header.length).map((e=>({text:e,tokens:this.lexer.inline(e)}))));return i}}lheading(e){const t=this.rules.block.lheading.exec(e);if(t)return{type:"heading",raw:t[0],depth:"="===t[2].charAt(0)?1:2,text:t[1],tokens:this.lexer.inline(t[1])}}paragraph(e){const t=this.rules.block.paragraph.exec(e);if(t){const e="\n"===t[1].charAt(t[1].length-1)?t[1].slice(0,-1):t[1];return{type:"paragraph",raw:t[0],text:e,tokens:this.lexer.inline(e)}}}text(e){const t=this.rules.block.text.exec(e);if(t)return{type:"text",raw:t[0],text:t[0],tokens:this.lexer.inline(t[0])}}escape(e){const t=this.rules.inline.escape.exec(e);if(t)return{type:"escape",raw:t[0],text:c(t[1])}}tag(e){const t=this.rules.inline.tag.exec(e);if(t)return!this.lexer.state.inLink&&/^/i.test(t[0])&&(this.lexer.state.inLink=!1),!this.lexer.state.inRawBlock&&/^<(pre|code|kbd|script)(\s|>)/i.test(t[0])?this.lexer.state.inRawBlock=!0:this.lexer.state.inRawBlock&&/^<\/(pre|code|kbd|script)(\s|>)/i.test(t[0])&&(this.lexer.state.inRawBlock=!1),{type:"html",raw:t[0],inLink:this.lexer.state.inLink,inRawBlock:this.lexer.state.inRawBlock,block:!1,text:t[0]}}link(e){const t=this.rules.inline.link.exec(e);if(t){const e=t[2].trim();if(!this.options.pedantic&&/^$/.test(e))return;const t=x(e.slice(0,-1),"\\");if((e.length-t.length)%2==0)return}else{const e=function(e,t){if(-1===e.indexOf(t[1]))return-1;let n=0;for(let s=0;s-1){const n=(0===t[0].indexOf("!")?5:4)+t[1].length+e;t[2]=t[2].substring(0,e),t[0]=t[0].substring(0,n).trim(),t[3]=""}}let n=t[2],s="";if(this.options.pedantic){const e=/^([^'"]*[^\s])\s+(['"])(.*)\2/.exec(n);e&&(n=e[1],s=e[3])}else s=t[3]?t[3].slice(1,-1):"";return n=n.trim(),/^$/.test(e)?n.slice(1):n.slice(1,-1)),b(t,{href:n?n.replace(this.rules.inline.anyPunctuation,"$1"):n,title:s?s.replace(this.rules.inline.anyPunctuation,"$1"):s},t[0],this.lexer)}}reflink(e,t){let n;if((n=this.rules.inline.reflink.exec(e))||(n=this.rules.inline.nolink.exec(e))){const e=t[(n[2]||n[1]).replace(/\s+/g," ").toLowerCase()];if(!e){const e=n[0].charAt(0);return{type:"text",raw:e,text:e}}return b(n,e,n[0],this.lexer)}}emStrong(e,t,n=""){let s=this.rules.inline.emStrongLDelim.exec(e);if(!s)return;if(s[3]&&n.match(/[\p{L}\p{N}]/u))return;if(!(s[1]||s[2]||"")||!n||this.rules.inline.punctuation.exec(n)){const n=[...s[0]].length-1;let r,i,l=n,o=0;const a="*"===s[0][0]?this.rules.inline.emStrongRDelimAst:this.rules.inline.emStrongRDelimUnd;for(a.lastIndex=0,t=t.slice(-1*e.length+n);null!=(s=a.exec(t));){if(r=s[1]||s[2]||s[3]||s[4]||s[5]||s[6],!r)continue;if(i=[...r].length,s[3]||s[4]){l+=i;continue}if((s[5]||s[6])&&n%3&&!((n+i)%3)){o+=i;continue}if(l-=i,l>0)continue;i=Math.min(i,i+l+o);const t=[...s[0]][0].length,a=e.slice(0,n+s.index+t+i);if(Math.min(n,i)%2){const e=a.slice(1,-1);return{type:"em",raw:a,text:e,tokens:this.lexer.inlineTokens(e)}}const c=a.slice(2,-2);return{type:"strong",raw:a,text:c,tokens:this.lexer.inlineTokens(c)}}}}codespan(e){const t=this.rules.inline.code.exec(e);if(t){let e=t[2].replace(/\n/g," ");const n=/[^ ]/.test(e),s=/^ /.test(e)&&/ $/.test(e);return n&&s&&(e=e.substring(1,e.length-1)),e=c(e,!0),{type:"codespan",raw:t[0],text:e}}}br(e){const t=this.rules.inline.br.exec(e);if(t)return{type:"br",raw:t[0]}}del(e){const t=this.rules.inline.del.exec(e);if(t)return{type:"del",raw:t[0],text:t[2],tokens:this.lexer.inlineTokens(t[2])}}autolink(e){const t=this.rules.inline.autolink.exec(e);if(t){let e,n;return"@"===t[2]?(e=c(t[1]),n="mailto:"+e):(e=c(t[1]),n=e),{type:"link",raw:t[0],text:e,href:n,tokens:[{type:"text",raw:e,text:e}]}}}url(e){let t;if(t=this.rules.inline.url.exec(e)){let e,n;if("@"===t[2])e=c(t[0]),n="mailto:"+e;else{let s;do{s=t[0],t[0]=this.rules.inline._backpedal.exec(t[0])?.[0]??""}while(s!==t[0]);e=c(t[0]),n="www."===t[1]?"http://"+t[0]:t[0]}return{type:"link",raw:t[0],text:e,href:n,tokens:[{type:"text",raw:e,text:e}]}}}inlineText(e){const t=this.rules.inline.text.exec(e);if(t){let e;return e=this.lexer.state.inRawBlock?t[0]:c(t[0]),{type:"text",raw:t[0],text:e}}}}const m=/^ {0,3}((?:-[\t ]*){3,}|(?:_[ \t]*){3,}|(?:\*[ \t]*){3,})(?:\n+|$)/,y=/(?:[*+-]|\d{1,9}[.)])/,$=k(/^(?!bull |blockCode|fences|blockquote|heading|html)((?:.|\n(?!\s*?\n|bull |blockCode|fences|blockquote|heading|html))+?)\n {0,3}(=+|-+) *(?:\n+|$)/).replace(/bull/g,y).replace(/blockCode/g,/ {4}/).replace(/fences/g,/ {0,3}(?:`{3,}|~{3,})/).replace(/blockquote/g,/ {0,3}>/).replace(/heading/g,/ {0,3}#{1,6}/).replace(/html/g,/ {0,3}<[^\n>]+>\n/).getRegex(),z=/^([^\n]+(?:\n(?!hr|heading|lheading|blockquote|fences|list|html|table| +\n)[^\n]+)*)/,T=/(?!\s*\])(?:\\.|[^\[\]\\])+/,R=k(/^ {0,3}\[(label)\]: *(?:\n *)?([^<\s][^\s]*|<.*?>)(?:(?: +(?:\n *)?| *\n *)(title))? *(?:\n+|$)/).replace("label",T).replace("title",/(?:"(?:\\"?|[^"\\])*"|'[^'\n]*(?:\n[^'\n]+)*\n?'|\([^()]*\))/).getRegex(),_=k(/^( {0,3}bull)([ \t][^\n]+?)?(?:\n|$)/).replace(/bull/g,y).getRegex(),A="address|article|aside|base|basefont|blockquote|body|caption|center|col|colgroup|dd|details|dialog|dir|div|dl|dt|fieldset|figcaption|figure|footer|form|frame|frameset|h[1-6]|head|header|hr|html|iframe|legend|li|link|main|menu|menuitem|meta|nav|noframes|ol|optgroup|option|p|param|search|section|summary|table|tbody|td|tfoot|th|thead|title|tr|track|ul",S=/|$))/,I=k("^ {0,3}(?:<(script|pre|style|textarea)[\\s>][\\s\\S]*?(?:[^\\n]*\\n+|$)|comment[^\\n]*(\\n+|$)|<\\?[\\s\\S]*?(?:\\?>\\n*|$)|\\n*|$)|\\n*|$)|)[\\s\\S]*?(?:(?:\\n *)+\\n|$)|<(?!script|pre|style|textarea)([a-z][\\w-]*)(?:attribute)*? */?>(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n *)+\\n|$)|(?=[ \\t]*(?:\\n|$))[\\s\\S]*?(?:(?:\\n *)+\\n|$))","i").replace("comment",S).replace("tag",A).replace("attribute",/ +[a-zA-Z:_][\w.:-]*(?: *= *"[^"\n]*"| *= *'[^'\n]*'| *= *[^\s"'=<>`]+)?/).getRegex(),E=k(z).replace("hr",m).replace("heading"," {0,3}#{1,6}(?:\\s|$)").replace("|lheading","").replace("|table","").replace("blockquote"," {0,3}>").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)]) ").replace("html",")|<(?:script|pre|style|textarea|!--)").replace("tag",A).getRegex(),q={blockquote:k(/^( {0,3}> ?(paragraph|[^\n]*)(?:\n|$))+/).replace("paragraph",E).getRegex(),code:/^( {4}[^\n]+(?:\n(?: *(?:\n|$))*)?)+/,def:R,fences:/^ {0,3}(`{3,}(?=[^`\n]*(?:\n|$))|~{3,})([^\n]*)(?:\n|$)(?:|([\s\S]*?)(?:\n|$))(?: {0,3}\1[~`]* *(?=\n|$)|$)/,heading:/^ {0,3}(#{1,6})(?=\s|$)(.*)(?:\n+|$)/,hr:m,html:I,lheading:$,list:_,newline:/^(?: *(?:\n|$))+/,paragraph:E,table:f,text:/^[^\n]+/},Z=k("^ *([^\\n ].*)\\n {0,3}((?:\\| *)?:?-+:? *(?:\\| *:?-+:? *)*(?:\\| *)?)(?:\\n((?:(?! *\\n|hr|heading|blockquote|code|fences|list|html).*(?:\\n|$))*)\\n*|$)").replace("hr",m).replace("heading"," {0,3}#{1,6}(?:\\s|$)").replace("blockquote"," {0,3}>").replace("code"," {4}[^\\n]").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)]) ").replace("html",")|<(?:script|pre|style|textarea|!--)").replace("tag",A).getRegex(),L={...q,table:Z,paragraph:k(z).replace("hr",m).replace("heading"," {0,3}#{1,6}(?:\\s|$)").replace("|lheading","").replace("table",Z).replace("blockquote"," {0,3}>").replace("fences"," {0,3}(?:`{3,}(?=[^`\\n]*\\n)|~{3,})[^\\n]*\\n").replace("list"," {0,3}(?:[*+-]|1[.)]) ").replace("html",")|<(?:script|pre|style|textarea|!--)").replace("tag",A).getRegex()},P={...q,html:k("^ *(?:comment *(?:\\n|\\s*$)|<(tag)[\\s\\S]+? *(?:\\n{2,}|\\s*$)|\\s]*)*?/?> *(?:\\n{2,}|\\s*$))").replace("comment",S).replace(/tag/g,"(?!(?:a|em|strong|small|s|cite|q|dfn|abbr|data|time|code|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo|span|br|wbr|ins|del|img)\\b)\\w+(?!:|[^\\w\\s@]*@)\\b").getRegex(),def:/^ *\[([^\]]+)\]: *]+)>?(?: +(["(][^\n]+[")]))? *(?:\n+|$)/,heading:/^(#{1,6})(.*)(?:\n+|$)/,fences:f,lheading:/^(.+?)\n {0,3}(=+|-+) *(?:\n+|$)/,paragraph:k(z).replace("hr",m).replace("heading"," *#{1,6} *[^\n]").replace("lheading",$).replace("|table","").replace("blockquote"," {0,3}>").replace("|fences","").replace("|list","").replace("|html","").replace("|tag","").getRegex()},Q=/^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/,v=/^( {2,}|\\)\n(?!\s*$)/,B="\\p{P}\\p{S}",C=k(/^((?![*_])[\spunctuation])/,"u").replace(/punctuation/g,B).getRegex(),M=k(/^(?:\*+(?:((?!\*)[punct])|[^\s*]))|^_+(?:((?!_)[punct])|([^\s_]))/,"u").replace(/punct/g,B).getRegex(),O=k("^[^_*]*?__[^_*]*?\\*[^_*]*?(?=__)|[^*]+(?=[^*])|(?!\\*)[punct](\\*+)(?=[\\s]|$)|[^punct\\s](\\*+)(?!\\*)(?=[punct\\s]|$)|(?!\\*)[punct\\s](\\*+)(?=[^punct\\s])|[\\s](\\*+)(?!\\*)(?=[punct])|(?!\\*)[punct](\\*+)(?!\\*)(?=[punct])|[^punct\\s](\\*+)(?=[^punct\\s])","gu").replace(/punct/g,B).getRegex(),D=k("^[^_*]*?\\*\\*[^_*]*?_[^_*]*?(?=\\*\\*)|[^_]+(?=[^_])|(?!_)[punct](_+)(?=[\\s]|$)|[^punct\\s](_+)(?!_)(?=[punct\\s]|$)|(?!_)[punct\\s](_+)(?=[^punct\\s])|[\\s](_+)(?!_)(?=[punct])|(?!_)[punct](_+)(?!_)(?=[punct])","gu").replace(/punct/g,B).getRegex(),j=k(/\\([punct])/,"gu").replace(/punct/g,B).getRegex(),H=k(/^<(scheme:[^\s\x00-\x1f<>]*|email)>/).replace("scheme",/[a-zA-Z][a-zA-Z0-9+.-]{1,31}/).replace("email",/[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+(@)[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)+(?![-_])/).getRegex(),U=k(S).replace("(?:--\x3e|$)","--\x3e").getRegex(),X=k("^comment|^|^<[a-zA-Z][\\w-]*(?:attribute)*?\\s*/?>|^<\\?[\\s\\S]*?\\?>|^|^").replace("comment",U).replace("attribute",/\s+[a-zA-Z:_][\w.:-]*(?:\s*=\s*"[^"]*"|\s*=\s*'[^']*'|\s*=\s*[^\s"'=<>`]+)?/).getRegex(),F=/(?:\[(?:\\.|[^\[\]\\])*\]|\\.|`[^`]*`|[^\[\]\\`])*?/,N=k(/^!?\[(label)\]\(\s*(href)(?:\s+(title))?\s*\)/).replace("label",F).replace("href",/<(?:\\.|[^\n<>\\])+>|[^\s\x00-\x1f]*/).replace("title",/"(?:\\"?|[^"\\])*"|'(?:\\'?|[^'\\])*'|\((?:\\\)?|[^)\\])*\)/).getRegex(),G=k(/^!?\[(label)\]\[(ref)\]/).replace("label",F).replace("ref",T).getRegex(),J=k(/^!?\[(ref)\](?:\[\])?/).replace("ref",T).getRegex(),K={_backpedal:f,anyPunctuation:j,autolink:H,blockSkip:/\[[^[\]]*?\]\([^\(\)]*?\)|`[^`]*?`|<[^<>]*?>/g,br:v,code:/^(`+)([^`]|[^`][\s\S]*?[^`])\1(?!`)/,del:f,emStrongLDelim:M,emStrongRDelimAst:O,emStrongRDelimUnd:D,escape:Q,link:N,nolink:J,punctuation:C,reflink:G,reflinkSearch:k("reflink|nolink(?!\\()","g").replace("reflink",G).replace("nolink",J).getRegex(),tag:X,text:/^(`+|[^`])(?:(?= {2,}\n)|[\s\S]*?(?:(?=[\\t+" ".repeat(n.length)));e;)if(!(this.options.extensions&&this.options.extensions.block&&this.options.extensions.block.some((s=>!!(n=s.call({lexer:this},e,t))&&(e=e.substring(n.raw.length),t.push(n),!0)))))if(n=this.tokenizer.space(e))e=e.substring(n.raw.length),1===n.raw.length&&t.length>0?t[t.length-1].raw+="\n":t.push(n);else if(n=this.tokenizer.code(e))e=e.substring(n.raw.length),s=t[t.length-1],!s||"paragraph"!==s.type&&"text"!==s.type?t.push(n):(s.raw+="\n"+n.raw,s.text+="\n"+n.text,this.inlineQueue[this.inlineQueue.length-1].src=s.text);else if(n=this.tokenizer.fences(e))e=e.substring(n.raw.length),t.push(n);else if(n=this.tokenizer.heading(e))e=e.substring(n.raw.length),t.push(n);else if(n=this.tokenizer.hr(e))e=e.substring(n.raw.length),t.push(n);else if(n=this.tokenizer.blockquote(e))e=e.substring(n.raw.length),t.push(n);else if(n=this.tokenizer.list(e))e=e.substring(n.raw.length),t.push(n);else if(n=this.tokenizer.html(e))e=e.substring(n.raw.length),t.push(n);else if(n=this.tokenizer.def(e))e=e.substring(n.raw.length),s=t[t.length-1],!s||"paragraph"!==s.type&&"text"!==s.type?this.tokens.links[n.tag]||(this.tokens.links[n.tag]={href:n.href,title:n.title}):(s.raw+="\n"+n.raw,s.text+="\n"+n.raw,this.inlineQueue[this.inlineQueue.length-1].src=s.text);else if(n=this.tokenizer.table(e))e=e.substring(n.raw.length),t.push(n);else if(n=this.tokenizer.lheading(e))e=e.substring(n.raw.length),t.push(n);else{if(r=e,this.options.extensions&&this.options.extensions.startBlock){let t=1/0;const n=e.slice(1);let s;this.options.extensions.startBlock.forEach((e=>{s=e.call({lexer:this},n),"number"==typeof s&&s>=0&&(t=Math.min(t,s))})),t<1/0&&t>=0&&(r=e.substring(0,t+1))}if(this.state.top&&(n=this.tokenizer.paragraph(r)))s=t[t.length-1],i&&"paragraph"===s.type?(s.raw+="\n"+n.raw,s.text+="\n"+n.text,this.inlineQueue.pop(),this.inlineQueue[this.inlineQueue.length-1].src=s.text):t.push(n),i=r.length!==e.length,e=e.substring(n.raw.length);else if(n=this.tokenizer.text(e))e=e.substring(n.raw.length),s=t[t.length-1],s&&"text"===s.type?(s.raw+="\n"+n.raw,s.text+="\n"+n.text,this.inlineQueue.pop(),this.inlineQueue[this.inlineQueue.length-1].src=s.text):t.push(n);else if(e){const t="Infinite loop on byte: "+e.charCodeAt(0);if(this.options.silent){console.error(t);break}throw new Error(t)}}return this.state.top=!0,t}inline(e,t=[]){return this.inlineQueue.push({src:e,tokens:t}),t}inlineTokens(e,t=[]){let n,s,r,i,l,o,a=e;if(this.tokens.links){const e=Object.keys(this.tokens.links);if(e.length>0)for(;null!=(i=this.tokenizer.rules.inline.reflinkSearch.exec(a));)e.includes(i[0].slice(i[0].lastIndexOf("[")+1,-1))&&(a=a.slice(0,i.index)+"["+"a".repeat(i[0].length-2)+"]"+a.slice(this.tokenizer.rules.inline.reflinkSearch.lastIndex))}for(;null!=(i=this.tokenizer.rules.inline.blockSkip.exec(a));)a=a.slice(0,i.index)+"["+"a".repeat(i[0].length-2)+"]"+a.slice(this.tokenizer.rules.inline.blockSkip.lastIndex);for(;null!=(i=this.tokenizer.rules.inline.anyPunctuation.exec(a));)a=a.slice(0,i.index)+"++"+a.slice(this.tokenizer.rules.inline.anyPunctuation.lastIndex);for(;e;)if(l||(o=""),l=!1,!(this.options.extensions&&this.options.extensions.inline&&this.options.extensions.inline.some((s=>!!(n=s.call({lexer:this},e,t))&&(e=e.substring(n.raw.length),t.push(n),!0)))))if(n=this.tokenizer.escape(e))e=e.substring(n.raw.length),t.push(n);else if(n=this.tokenizer.tag(e))e=e.substring(n.raw.length),s=t[t.length-1],s&&"text"===n.type&&"text"===s.type?(s.raw+=n.raw,s.text+=n.text):t.push(n);else if(n=this.tokenizer.link(e))e=e.substring(n.raw.length),t.push(n);else if(n=this.tokenizer.reflink(e,this.tokens.links))e=e.substring(n.raw.length),s=t[t.length-1],s&&"text"===n.type&&"text"===s.type?(s.raw+=n.raw,s.text+=n.text):t.push(n);else if(n=this.tokenizer.emStrong(e,a,o))e=e.substring(n.raw.length),t.push(n);else if(n=this.tokenizer.codespan(e))e=e.substring(n.raw.length),t.push(n);else if(n=this.tokenizer.br(e))e=e.substring(n.raw.length),t.push(n);else if(n=this.tokenizer.del(e))e=e.substring(n.raw.length),t.push(n);else if(n=this.tokenizer.autolink(e))e=e.substring(n.raw.length),t.push(n);else if(this.state.inLink||!(n=this.tokenizer.url(e))){if(r=e,this.options.extensions&&this.options.extensions.startInline){let t=1/0;const n=e.slice(1);let s;this.options.extensions.startInline.forEach((e=>{s=e.call({lexer:this},n),"number"==typeof s&&s>=0&&(t=Math.min(t,s))})),t<1/0&&t>=0&&(r=e.substring(0,t+1))}if(n=this.tokenizer.inlineText(r))e=e.substring(n.raw.length),"_"!==n.raw.slice(-1)&&(o=n.raw.slice(-1)),l=!0,s=t[t.length-1],s&&"text"===s.type?(s.raw+=n.raw,s.text+=n.text):t.push(n);else if(e){const t="Infinite loop on byte: "+e.charCodeAt(0);if(this.options.silent){console.error(t);break}throw new Error(t)}}else e=e.substring(n.raw.length),t.push(n);return t}}class se{options;constructor(t){this.options=t||e.defaults}code(e,t,n){const s=(t||"").match(/^\S*/)?.[0];return e=e.replace(/\n$/,"")+"\n",s?'
'+(n?e:c(e,!0))+"
\n":"
"+(n?e:c(e,!0))+"
\n"}blockquote(e){return`
\n${e}
\n`}html(e,t){return e}heading(e,t,n){return`${e}\n`}hr(){return"
\n"}list(e,t,n){const s=t?"ol":"ul";return"<"+s+(t&&1!==n?' start="'+n+'"':"")+">\n"+e+"\n"}listitem(e,t,n){return`
  • ${e}
  • \n`}checkbox(e){return"'}paragraph(e){return`

    ${e}

    \n`}table(e,t){return t&&(t=`${t}`),"\n\n"+e+"\n"+t+"
    \n"}tablerow(e){return`\n${e}\n`}tablecell(e,t){const n=t.header?"th":"td";return(t.align?`<${n} align="${t.align}">`:`<${n}>`)+e+`\n`}strong(e){return`${e}`}em(e){return`${e}`}codespan(e){return`${e}`}br(){return"
    "}del(e){return`${e}`}link(e,t,n){const s=g(e);if(null===s)return n;let r='
    ",r}image(e,t,n){const s=g(e);if(null===s)return n;let r=`${n}0&&"paragraph"===n.tokens[0].type?(n.tokens[0].text=e+" "+n.tokens[0].text,n.tokens[0].tokens&&n.tokens[0].tokens.length>0&&"text"===n.tokens[0].tokens[0].type&&(n.tokens[0].tokens[0].text=e+" "+n.tokens[0].tokens[0].text)):n.tokens.unshift({type:"text",text:e+" "}):o+=e+" "}o+=this.parse(n.tokens,i),l+=this.renderer.listitem(o,r,!!s)}n+=this.renderer.list(l,t,s);continue}case"html":{const e=r;n+=this.renderer.html(e.text,e.block);continue}case"paragraph":{const e=r;n+=this.renderer.paragraph(this.parseInline(e.tokens));continue}case"text":{let i=r,l=i.tokens?this.parseInline(i.tokens):i.text;for(;s+1{const r=e[s].flat(1/0);n=n.concat(this.walkTokens(r,t))})):e.tokens&&(n=n.concat(this.walkTokens(e.tokens,t)))}}return n}use(...e){const t=this.defaults.extensions||{renderers:{},childTokens:{}};return e.forEach((e=>{const n={...e};if(n.async=this.defaults.async||n.async||!1,e.extensions&&(e.extensions.forEach((e=>{if(!e.name)throw new Error("extension name required");if("renderer"in e){const n=t.renderers[e.name];t.renderers[e.name]=n?function(...t){let s=e.renderer.apply(this,t);return!1===s&&(s=n.apply(this,t)),s}:e.renderer}if("tokenizer"in e){if(!e.level||"block"!==e.level&&"inline"!==e.level)throw new Error("extension level must be 'block' or 'inline'");const n=t[e.level];n?n.unshift(e.tokenizer):t[e.level]=[e.tokenizer],e.start&&("block"===e.level?t.startBlock?t.startBlock.push(e.start):t.startBlock=[e.start]:"inline"===e.level&&(t.startInline?t.startInline.push(e.start):t.startInline=[e.start]))}"childTokens"in e&&e.childTokens&&(t.childTokens[e.name]=e.childTokens)})),n.extensions=t),e.renderer){const t=this.defaults.renderer||new se(this.defaults);for(const n in e.renderer){if(!(n in t))throw new Error(`renderer '${n}' does not exist`);if("options"===n)continue;const s=n,r=e.renderer[s],i=t[s];t[s]=(...e)=>{let n=r.apply(t,e);return!1===n&&(n=i.apply(t,e)),n||""}}n.renderer=t}if(e.tokenizer){const t=this.defaults.tokenizer||new w(this.defaults);for(const n in e.tokenizer){if(!(n in t))throw new Error(`tokenizer '${n}' does not exist`);if(["options","rules","lexer"].includes(n))continue;const s=n,r=e.tokenizer[s],i=t[s];t[s]=(...e)=>{let n=r.apply(t,e);return!1===n&&(n=i.apply(t,e)),n}}n.tokenizer=t}if(e.hooks){const t=this.defaults.hooks||new le;for(const n in e.hooks){if(!(n in t))throw new Error(`hook '${n}' does not exist`);if("options"===n)continue;const s=n,r=e.hooks[s],i=t[s];le.passThroughHooks.has(n)?t[s]=e=>{if(this.defaults.async)return Promise.resolve(r.call(t,e)).then((e=>i.call(t,e)));const n=r.call(t,e);return i.call(t,n)}:t[s]=(...e)=>{let n=r.apply(t,e);return!1===n&&(n=i.apply(t,e)),n}}n.hooks=t}if(e.walkTokens){const t=this.defaults.walkTokens,s=e.walkTokens;n.walkTokens=function(e){let n=[];return n.push(s.call(this,e)),t&&(n=n.concat(t.call(this,e))),n}}this.defaults={...this.defaults,...n}})),this}setOptions(e){return this.defaults={...this.defaults,...e},this}lexer(e,t){return ne.lex(e,t??this.defaults)}parser(e,t){return ie.parse(e,t??this.defaults)}#e(e,t){return(n,s)=>{const r={...s},i={...this.defaults,...r};!0===this.defaults.async&&!1===r.async&&(i.silent||console.warn("marked(): The async option was set to true by an extension. The async: false option sent to parse will be ignored."),i.async=!0);const l=this.#t(!!i.silent,!!i.async);if(null==n)return l(new Error("marked(): input parameter is undefined or null"));if("string"!=typeof n)return l(new Error("marked(): input parameter is of type "+Object.prototype.toString.call(n)+", string expected"));if(i.hooks&&(i.hooks.options=i),i.async)return Promise.resolve(i.hooks?i.hooks.preprocess(n):n).then((t=>e(t,i))).then((e=>i.hooks?i.hooks.processAllTokens(e):e)).then((e=>i.walkTokens?Promise.all(this.walkTokens(e,i.walkTokens)).then((()=>e)):e)).then((e=>t(e,i))).then((e=>i.hooks?i.hooks.postprocess(e):e)).catch(l);try{i.hooks&&(n=i.hooks.preprocess(n));let s=e(n,i);i.hooks&&(s=i.hooks.processAllTokens(s)),i.walkTokens&&this.walkTokens(s,i.walkTokens);let r=t(s,i);return i.hooks&&(r=i.hooks.postprocess(r)),r}catch(e){return l(e)}}}#t(e,t){return n=>{if(n.message+="\nPlease report this to https://github.com/markedjs/marked.",e){const e="

    An error occurred:

    "+c(n.message+"",!0)+"
    ";return t?Promise.resolve(e):e}if(t)return Promise.reject(n);throw n}}}const ae=new oe;function ce(e,t){return ae.parse(e,t)}ce.options=ce.setOptions=function(e){return ae.setOptions(e),ce.defaults=ae.defaults,n(ce.defaults),ce},ce.getDefaults=t,ce.defaults=e.defaults,ce.use=function(...e){return ae.use(...e),ce.defaults=ae.defaults,n(ce.defaults),ce},ce.walkTokens=function(e,t){return ae.walkTokens(e,t)},ce.parseInline=ae.parseInline,ce.Parser=ie,ce.parser=ie.parse,ce.Renderer=se,ce.TextRenderer=re,ce.Lexer=ne,ce.lexer=ne.lex,ce.Tokenizer=w,ce.Hooks=le,ce.parse=ce;const he=ce.options,pe=ce.setOptions,ue=ce.use,ke=ce.walkTokens,ge=ce.parseInline,fe=ce,de=ie.parse,xe=ne.lex;e.Hooks=le,e.Lexer=ne,e.Marked=oe,e.Parser=ie,e.Renderer=se,e.TextRenderer=re,e.Tokenizer=w,e.getDefaults=t,e.lexer=xe,e.marked=ce,e.options=he,e.parse=fe,e.parseInline=ge,e.parser=de,e.setOptions=pe,e.use=ue,e.walkTokens=ke})); 7 | -------------------------------------------------------------------------------- /includes/WidgetForm.php: -------------------------------------------------------------------------------- 1 | addField( 37 | (new CWidgetFieldSelect('service', _('Service'), [ 38 | 0 => 'OpenAI', 39 | 1 => 'Custom', 40 | ])) 41 | ->setDefault(0) 42 | ->setFlags(CWidgetField::FLAG_LABEL_ASTERISK | CWidgetField::FLAG_DISABLED) 43 | ) 44 | ->addField( 45 | (new CWidgetFieldTextBox('endpoint', _('Endpoint'))) 46 | ->setDefault('https://api.openai.com/v1/chat/completions') 47 | ->setFlags(CWidgetField::FLAG_NOT_EMPTY | CWidgetField::FLAG_LABEL_ASTERISK | CWidgetField::FLAG_DISABLED) 48 | ) 49 | ->addField( 50 | (new CWidgetFieldTextBox('token', _('Token'))) 51 | ->setFlags(CWidgetField::FLAG_NOT_EMPTY | CWidgetField::FLAG_LABEL_ASTERISK) 52 | ) 53 | ->addField( 54 | (new CWidgetFieldSelect('model', _('Model'), [ 55 | 0 => 'GPT-3.5 Turbo', 56 | 1 => 'Other models are available in PRO version', 57 | ])) 58 | ->setDefault(0) 59 | ->setFlags(CWidgetField::FLAG_DISABLED) 60 | ) 61 | ->addField( 62 | (new CWidgetFieldTextBox('temperature', _('Temperature'))) 63 | ->setDefault('1') 64 | ->setFlags(CWidgetField::FLAG_DISABLED) 65 | ) 66 | ->addField( 67 | (new CWidgetFieldTextBox('top_p', _('Top P'))) 68 | ->setDefault('1') 69 | ->setFlags(CWidgetField::FLAG_DISABLED) 70 | ) 71 | ->addField( 72 | (new CWidgetFieldTextBox('max_tokens', _('Max tokens'))) 73 | ->setDefault('16') 74 | ->setFlags(CWidgetField::FLAG_DISABLED) 75 | ) 76 | ->addField( 77 | (new CWidgetFieldTextBox('n', _('N'))) 78 | ->setDefault('1') 79 | ->setFlags(CWidgetField::FLAG_DISABLED) 80 | ) 81 | ; 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "manifest_version": 2.0, 3 | "id": "chatgpt", 4 | "type": "widget", 5 | "name": "ChatGPT widget", 6 | "namespace": "OpenAI", 7 | "version": "2.0", 8 | "author": "initMAX s.r.o.", 9 | "url": "https://www.initmax.com", 10 | "description": "Chatting widget which using OpenAI or custom provider LLM", 11 | "actions": { 12 | "widget.openai.view": { 13 | "class": "WidgetView" 14 | } 15 | }, 16 | "widget": { 17 | "name": "ChatGPT", 18 | "size": { 19 | "width": 4, 20 | "height": 4 21 | }, 22 | "refresh_rate": 0, 23 | "js_class": "CWidgetOpenAI" 24 | }, 25 | "assets": { 26 | "css": [ 27 | "widget.css", 28 | "form.css" 29 | ], 30 | "js": [ 31 | "marked.min.js", 32 | "class.widget.js" 33 | ] 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "openai", 3 | "version": "1.0.0", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "openai", 9 | "version": "1.0.0", 10 | "license": "ISC", 11 | "dependencies": { 12 | "marked": "^12.0.2" 13 | } 14 | }, 15 | "node_modules/marked": { 16 | "version": "12.0.2", 17 | "resolved": "https://registry.npmjs.org/marked/-/marked-12.0.2.tgz", 18 | "integrity": "sha512-qXUm7e/YKFoqFPYPa3Ukg9xlI5cyAtGmyEIzMfW//m6kXwCy2Ps9DYf5ioijFKQ8qyuscrHoY04iJGctu2Kg0Q==", 19 | "bin": { 20 | "marked": "bin/marked.js" 21 | }, 22 | "engines": { 23 | "node": ">= 18" 24 | } 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "openai", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "marked": "^12.0.2" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /views/widget.edit.js.php: -------------------------------------------------------------------------------- 1 | //