Compare commits
662 commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9989ce8df9 | |||
| f5a2c391b3 | |||
| 3fa534e464 | |||
| 107ea4449d | |||
| fb06e94ff3 | |||
| b318a1c376 | |||
| b246405845 | |||
| f7cf33d9df | |||
| 71bb6c059d | |||
| 45ebddb586 | |||
| 3b8ad3fb95 | |||
| 5103eec5ac | |||
| 0bebb0c1f2 | |||
| 2c66e30e66 | |||
| 5230b7d889 | |||
| cb40c8edab | |||
| bccd7a24cf | |||
| a413cbd37e | |||
| 54e1069ce0 | |||
| 72e64ce7b4 | |||
| 3f5e8eee1c | |||
| 45cb0c6371 | |||
| c4d9644e15 | |||
| 20b244b1e8 | |||
| 4042763344 | |||
| 511e198229 | |||
| 27c19def7d | |||
| cf921bd28a | |||
| 9aa42524d2 | |||
| dbd36c4250 | |||
| 41d6d02af7 | |||
| 0907346d3d | |||
| 527660fd3b | |||
| 28445fdb7e | |||
| ce4c676501 | |||
| 468a4fdbb7 | |||
| f62d1f4664 | |||
| 8fbcec2b1e | |||
| 53f63866d2 | |||
| 23081e63e6 | |||
| 45e3088a54 | |||
| 402c5edc3d | |||
| 156b7550c1 | |||
| f39bee2b19 | |||
| 645f43be9d | |||
| 1f5b06ffd0 | |||
| 70869a360e | |||
| 73644e4ede | |||
| 0b1876461e | |||
| 3da2574a00 | |||
| 51bb163462 | |||
| d34e24a5fc | |||
| b45ac25faa | |||
| 8eac754e04 | |||
| be0adbd46e | |||
| e32a8fb604 | |||
| f992c26026 | |||
| 6a84e8b4c4 | |||
| a23e763913 | |||
| 2ff5c43531 | |||
| ea36abbea3 | |||
| 1e1225e2d8 | |||
| 8974c91a17 | |||
| 57c0407806 | |||
| 3295ffe832 | |||
| c5c72648b6 | |||
| aacaa866da | |||
| 8f30ebfa22 | |||
| 7146c4b2ee | |||
| 4bcf3c461b | |||
| 71fe5995b5 | |||
| 947000893e | |||
| fc25f3b0fc | |||
| 4582c90f2b | |||
| 4a99ec7f4e | |||
| c51e9e1533 | |||
| e8c158427a | |||
| de4b9d9b0d | |||
| d19c5a1dff | |||
| bb08ad812e | |||
| 88a444b0f4 | |||
| 3e313b2f86 | |||
| 428595f7ec | |||
| 08d1a56732 | |||
| a21ee09c97 | |||
| d95c7d597c | |||
| af9b6a923b | |||
| 8992b7491d | |||
| 04b923cda1 | |||
| 585f49a2d3 | |||
| 236d7e7ce2 | |||
| 59030bc6fb | |||
| 588fbc3c5e | |||
| 4b692abc5f | |||
| 65e4d41970 | |||
| 1169655267 | |||
| 10c004f95f | |||
| 50baf12650 | |||
| 9977ca85b8 | |||
| 7977246712 | |||
| 1f43cd8c4a | |||
| 9545be05d8 | |||
| 1567717d21 | |||
| dc452c8602 | |||
| a87b3e0b22 | |||
| 5d9c74ed3c | |||
| 7d32b949c3 | |||
| bc9f8cae39 | |||
| 387db0caf5 | |||
| 21d05286ad | |||
| 953e96012e | |||
| 852f2969dc | |||
| 3c5145196a | |||
| 55966f329b | |||
| 7dcab89e06 | |||
| f98e5ebd06 | |||
| 7b144bd1f9 | |||
| 5abb7c2e2e | |||
| 40cc22f1fd | |||
| a305060619 | |||
| 08c05eb894 | |||
| 30ceb24903 | |||
| 6f0d9a1b91 | |||
| 875eaf4ee7 | |||
| f7597aa646 | |||
| 09f3c1f9d7 | |||
| ac02f7a4c8 | |||
| f5542eb834 | |||
| 5b13f104b2 | |||
| 45484aa6fc | |||
| 7b70341735 | |||
| 8aab947a14 | |||
| bcc042c7fa | |||
| 47b3c23b9d | |||
| ff1834ffeb | |||
| f1b3c4258e | |||
| cbb79a5311 | |||
| 338f3dd248 | |||
| 7e019145c5 | |||
| 1efcb4d1be | |||
| 541f31b2db | |||
| 46588a7ea6 | |||
| 475bcde522 | |||
| 205d0fe1a9 | |||
| 6d7df4d62f | |||
| 304505a29e | |||
| 1565b68243 | |||
| 0aa90a3a24 | |||
| 5687aeb322 | |||
| 7fc77b1d0c | |||
| bd34c9a984 | |||
| a97e35ae82 | |||
| ffd0aabede | |||
| 39f6d7904d | |||
| 7fc051446e | |||
| 6afdb0404a | |||
| 5a295b19f0 | |||
| 54a82c1322 | |||
| d6c36fdfba | |||
| bead4a3520 | |||
| 4b039b2fab | |||
| 05a8b2bc13 | |||
| cd34722dcc | |||
| 93b6058449 | |||
| 0ac8ee7989 | |||
| f51ba0afbc | |||
| 35852cb76f | |||
| 357cb4c0e7 | |||
| dd40eaae57 | |||
| 81096be802 | |||
| c82e9e360b | |||
| 5009c46634 | |||
| b293fc966e | |||
| 8c9c90181e | |||
| 588e23fb4f | |||
| 94d0923acb | |||
| d561af0981 | |||
| c6d73e73bd | |||
| 3963b72147 | |||
| 5b47759263 | |||
| a8842408f7 | |||
| 12d33d5c7c | |||
| 3bf10e44ca | |||
| 1357a5b174 | |||
| 87bbc31887 | |||
| e39f92d6fa | |||
| 1f838a33db | |||
| 03bdd539f2 | |||
| cf4946dde9 | |||
| f4fae5672f | |||
| 49f3ea066e | |||
| 1aa2e6dfd9 | |||
| e1bf241f58 | |||
| 88add80f16 | |||
| 8d6368ada1 | |||
| 586da4dbd4 | |||
| 3ec393c3ba | |||
| 5157d8ba8b | |||
| ab5147e077 | |||
| 51c8fb594a | |||
| ccd15e8df4 | |||
| 7280ebc4da | |||
| 594e1492f2 | |||
| 2741f0ff7d | |||
| 91826f3c70 | |||
| 9b90a8bce8 | |||
| 6b0d7d449d | |||
| 5477f20493 | |||
| a6dfb450d1 | |||
| f1cdc524d4 | |||
| 5c69a8eed0 | |||
| 992fd38863 | |||
| 273034faf2 | |||
| a5b747e5a8 | |||
| ffb0683292 | |||
| bff10302eb | |||
| b6cbe6d346 | |||
| 770b1b0eaa | |||
| e295d5291c | |||
| 23eaf3c9b4 | |||
| 9a63f33ac1 | |||
| 081675ac9f | |||
| 286e40c9fd | |||
| b7d5a7c934 | |||
| fb91aae7f9 | |||
| 116f914490 | |||
| c86c8ad84e | |||
| 60b6aa8cf4 | |||
| 9e649e580a | |||
| 0629ccedec | |||
| 8638eb3567 | |||
| b41061f9a2 | |||
| 78a6113b64 | |||
| 24262f4596 | |||
| a088fb9fc8 | |||
| 7e21552ae4 | |||
| b75624a412 | |||
| b00e2e0135 | |||
| 36501ae20d | |||
| 68f2e3e637 | |||
| 8f8f9fc51a | |||
| 202fb1756d | |||
| f9adf00cad | |||
| f684b5738b | |||
| 577fa28400 | |||
| 28eb4cc2cd | |||
| b6bfc782d5 | |||
| 9a28cff96e | |||
| 122332dbf3 | |||
| 5c7dc816ee | |||
| f29597987d | |||
| 2117ea20aa | |||
| cc6b6050fe | |||
| f49d8e3330 | |||
| e7fbaa52ce | |||
| 5f1b770640 | |||
| 3a5b6e4f63 | |||
| 289ebc2377 | |||
| 09e19c50b9 | |||
| 5ec97b4894 | |||
| feabd5c391 | |||
| bf2cd42336 | |||
| eba06a1616 | |||
| 1ef62eb275 | |||
| 83af75e028 | |||
| f3d571ad49 | |||
| a966c3dd35 | |||
| 2054d9bfab | |||
| 76c68d35b2 | |||
| e3949600f6 | |||
| c07d6a9af4 | |||
| 2c0988ee97 | |||
| 305732a908 | |||
| e9fe0fa701 | |||
| 7c8ac65784 | |||
| 487e1b342b | |||
| 2be7dc8ce3 | |||
| fb13f5911c | |||
| 3e8214e008 | |||
| 7c5028bfd6 | |||
| 65ec28f77a | |||
| 659570821d | |||
| fcc9d8e36c | |||
| ab2aaa3994 | |||
| d970a96417 | |||
| 45a77e936f | |||
| dc3e5cd117 | |||
| b633a38f40 | |||
| 877a151822 | |||
| e7c6eab486 | |||
| 96cdaede5f | |||
| 5d9ce3d851 | |||
| 34427b9903 | |||
| 7b1391cbd5 | |||
| 24ae18af3a | |||
| 0e0e09917a | |||
| 8c9443a0c4 | |||
| 245f34ad3c | |||
| 795c65ce6f | |||
| 4f0f7818b9 | |||
| e33d6f4a0e | |||
| 0f7efaa28e | |||
| 3c99e6de08 | |||
| 175490cbc5 | |||
| bd04fa1b40 | |||
| 1093108716 | |||
| 68ba373383 | |||
| 7bcf60c193 | |||
| e2d6eb8c24 | |||
| 5aefc9a21c | |||
| 84415097c0 | |||
| fe2987f1dd | |||
| 3f042a6e71 | |||
| da8bb150d1 | |||
| 6ecab3c616 | |||
| f9ce3fb419 | |||
| bbea646325 | |||
| 1c7f19e92b | |||
| 5384c3825e | |||
| 40a38a1dbb | |||
| 8f0fa31856 | |||
| 6e7a0d5505 | |||
| 56762b1dec | |||
| 7595ba40be | |||
| 73e763197d | |||
| db4613b322 | |||
| 0f38e9f08f | |||
| 491e7441c0 | |||
| 226337a12e | |||
| e3858db952 | |||
| 9fcf933cf4 | |||
| 44e374ce97 | |||
| e6ea794f91 | |||
| 44df9c79a9 | |||
| 788ac4d87d | |||
| 30a51697bf | |||
| 62aa619211 | |||
| 1a6d6299d5 | |||
| 17161624da | |||
| 14e41f1bfc | |||
| c59418061a | |||
| d3abe80c1c | |||
| f333d68cd6 | |||
| ae38a8705e | |||
| d6419b57d5 | |||
| c92da26f17 | |||
| 104f0e21e7 | |||
| a3c3276c06 | |||
| 33dab80fe3 | |||
| 3f13f41fce | |||
| 17f6c61db9 | |||
| 7eb61b3f47 | |||
| a5cc841915 | |||
| 35433964e8 | |||
| 0f4c1d0ecd | |||
| 7265a9ebef | |||
| f9734978de | |||
| bb5b39b137 | |||
| b6686fe00d | |||
| 48c70f9dac | |||
| 9171352a31 | |||
| 1d2aa0cabb | |||
| 3b10e6a284 | |||
| 4e99594303 | |||
| c550c4291d | |||
| 57d8bd9975 | |||
| bf8db24d64 | |||
| 04470b533b | |||
| 4fc772e4b1 | |||
| 15ffb51d1b | |||
| 45db3d0f89 | |||
| a0296ba7aa | |||
| 9ecacb02fa | |||
| cf14ab4009 | |||
| 7233603814 | |||
| 78fd9e9617 | |||
| 2b4f116787 | |||
| a1d04c1e39 | |||
| 4cf4c646fa | |||
| 58e81908bd | |||
| 726d7364ed | |||
| c0b4bd3e34 | |||
| 6bb180fd65 | |||
| 3fb682c500 | |||
| aae3b15718 | |||
| f82cf82a52 | |||
| e76a693375 | |||
| c6a86bac12 | |||
| 8f14164094 | |||
| c005667f8c | |||
| 9202963ace | |||
| f66b4c4b29 | |||
| 455232a290 | |||
| 34c2f0e3f2 | |||
| 1f4259d526 | |||
| 6bbfcbe183 | |||
| 4755a80550 | |||
| 145957dcd3 | |||
| 5845efbc57 | |||
| 2a47fd6c65 | |||
| afccd1f719 | |||
| 4882324c8a | |||
| 192df5d523 | |||
| 4b197aff16 | |||
| ef2a4cf065 | |||
| e81be659a6 | |||
| c98e03ed4a | |||
| 4657a6f40b | |||
| 69fc248904 | |||
| e80e5baf8c | |||
| d3a6522f53 | |||
| 5e326b8b43 | |||
| 9d0099c3a1 | |||
| 0a3ecf6f9f | |||
| b830fb8678 | |||
| a0b8d5a61b | |||
| 175458d355 | |||
| 20d91f00d3 | |||
| 07ba6cb000 | |||
| 15f16fa387 | |||
| a22977406b | |||
| 5b259a2c5a | |||
| f514cb795a | |||
| aa82f2feee | |||
| 2938fe15da | |||
| 54a9ec1b52 | |||
| db5d393d50 | |||
| 7d3a60535e | |||
| 3f30e27da9 | |||
| 1d7b8b4e8b | |||
| 690e739e51 | |||
| 0cc5ce7400 | |||
| fdc330fb29 | |||
| d2e695d6b0 | |||
| f91c799012 | |||
| 51f7fc0947 | |||
| 7ae3a7181d | |||
| 298e5097ad | |||
| 1012d63314 | |||
| 137e71f819 | |||
| 478363d562 | |||
|
|
7e71bf3e15 | ||
|
|
96c69dc08b | ||
|
|
0a02759a89 | ||
|
|
3d5a9d7fab | ||
|
|
9c1a2eae34 | ||
| 4504108799 | |||
| 7d8c60b4b9 | |||
| 121eb4b5f2 | |||
| 310318e879 | |||
| 5abd8282d0 | |||
| fce6c76f07 | |||
| f3dc4c989c | |||
| 5fa88d49e0 | |||
| 4167906c00 | |||
| 78609fe3c7 | |||
| dbede36f10 | |||
| 44982757f5 | |||
| 2539161d71 | |||
| 83272e946c | |||
| 16f776f9b5 | |||
| 11465ab7eb | |||
| 78f6eea275 | |||
| 7ee2816f10 | |||
| dcdc237bfa | |||
| 38307a9710 | |||
| f99ba5a911 | |||
| 9861f1cefc | |||
| 153cb41918 | |||
| 176f07b345 | |||
| 254a760f7b | |||
| 79521d1659 | |||
| ca0ca5f72c | |||
| 54e50d94a3 | |||
| beb9e19c8c | |||
| ca7ed157e1 | |||
| 39190da88e | |||
| 94f73b1f66 | |||
| ea6a154d5d | |||
| 0993b8a712 | |||
| b610d2f1b9 | |||
| 903f48cd14 | |||
| 530456ea7f | |||
| dc27c7f082 | |||
| db96fd6efe | |||
| 83ce8b70ee | |||
| cea656ea17 | |||
| fb2129eead | |||
| 313e3dfc78 | |||
| d41fbdb5eb | |||
| 5275cbaa31 | |||
| 665a4a107a | |||
| b8aa71e206 | |||
| cad04a41bf | |||
| 50ee73e275 | |||
| 3aeb941638 | |||
| 6fd3c019ba | |||
| efce147586 | |||
| e706eb9fbb | |||
| 1fdacca368 | |||
| fd0ad0f785 | |||
| 219e01a9f3 | |||
| 3660a86afc | |||
| c05c218891 | |||
| cf3f9d806c | |||
| 25eac616fb | |||
| 542763983d | |||
| 116c5885f6 | |||
| c939c4f1dd | |||
| abc73de918 | |||
| 06c0768fe8 | |||
| 94dcbdda66 | |||
| 40b0b2d12c | |||
| d68c257b66 | |||
| 1e1e71d920 | |||
| 7b4735dd71 | |||
| 007cde436b | |||
| 511de99cef | |||
| 65039a255f | |||
| b9f7725886 | |||
| f4b303e23c | |||
| 18c1398758 | |||
| c4779fe55e | |||
| 059489b501 | |||
| eba68bb8ee | |||
| 1f1cdd8d22 | |||
| 573f5b4f7b | |||
| aa22617b97 | |||
| 1dc5ee9512 | |||
| 6c2a551a8e | |||
| 65cb081a2b | |||
| edda3464c6 | |||
| cd76b543e9 | |||
| 682f0e7fa3 | |||
| 9dbc16aef6 | |||
| f8a8cc97b0 | |||
| 98fb4c9713 | |||
| a440589bad | |||
| 39773cc7a9 | |||
| 076447086d | |||
| 95719cbe4c | |||
| a4ff41f13c | |||
| 7800c2d149 | |||
| 2a4cdedb8b | |||
| 7b07f3b6ab | |||
| 98d9c61af9 | |||
| eb3b30ef1c | |||
| 89643ae926 | |||
| 54f5019b6b | |||
| 9820144a6e | |||
| fccf542748 | |||
| 75113b15a8 | |||
| 454a8c92f4 | |||
| 1c6c48cfc9 | |||
| 808b0b1109 | |||
| 2a29f45781 | |||
| 131918ba09 | |||
| 47ac1cdc29 | |||
| 104812ec65 | |||
| 301325f925 | |||
| 74bc8556cc | |||
| c2cacf9c5e | |||
| 539935a730 | |||
| 6a6776eb3c | |||
| 6d5c93797a | |||
| 26535ba803 | |||
| b0da676a10 | |||
| d778dcb17b | |||
| 98783fc83d | |||
| 5ed5b21ad1 | |||
| 9c65220965 | |||
| ee4cec0013 | |||
| 068f011907 | |||
| df257e990e | |||
| 03a03c3a3f | |||
| 974e1e688a | |||
| b5896c2493 | |||
| 5221bc9ec5 | |||
| 65f1c762c1 | |||
| 5c3d772010 | |||
| 164a0972a4 | |||
| 1ccd1f9cc9 | |||
| e194dcf9e6 | |||
| 3c5c01f4ea | |||
| e50bcee8c7 | |||
| 198bcf8edb | |||
| 613a14ecfb | |||
| cd2dd0f6f6 | |||
| a13e3f7c51 | |||
| c9eabb0f0d | |||
| edb40ea8e0 | |||
| 416d0c7de6 | |||
| 24e0f3c3a6 | |||
| 22d7bdc16e | |||
| f67e25fcd3 | |||
| 93e46dfdaa | |||
| 0b591e663e | |||
| b3c35feff7 | |||
| 0ac7c4ed03 | |||
| cb9c94223d | |||
| 1f5c25ce79 | |||
| 2a45c5d7c4 | |||
| b6a0faf879 | |||
| f34e760697 | |||
| b6f69951f4 | |||
| 92f2c012f0 | |||
| 14d95994b9 | |||
| 4f7f0fff0e | |||
| d48791290a | |||
| 8831c56c90 | |||
| b9d6816644 | |||
| c258a61ad5 | |||
| 3326e07234 | |||
| 7bd5375d1a | |||
| 3dbadbafcb | |||
| b431ae6602 | |||
| 7e89d183ff | |||
| b2f143f664 | |||
| 860a460a93 | |||
| cda2d8f155 | |||
| 2a1f4305a2 | |||
| 090b42618b | |||
| f97451482d | |||
| 8a2072919a | |||
| 62749e9eba | |||
| 52e551734a | |||
| 00647f7edf | |||
| 4100e53c28 | |||
| 117ea78e39 | |||
| 91ddf87dce | |||
| 12b661fdc1 | |||
| 3375394ca5 | |||
| 23fe731d30 | |||
| 9f46a41abf | |||
| 13cea1b75c | |||
| 96076831ab | |||
| 02cd170eeb | |||
| 3befc141e5 | |||
| 64c14a30c9 | |||
| 1ee5492bd8 | |||
| 43b168a4b5 | |||
| 0dfabc46b3 | |||
| 79f849da6b | |||
| 81ac2ae8c6 | |||
| 68f3ada343 | |||
| 599c338a4a | |||
| f54ad8175c | |||
| cb61c130c3 | |||
| 1a5f54e576 | |||
| 2beeec3292 | |||
| 5f3f82748c | |||
| 5b0d274e5e | |||
| dc0055d9e6 | |||
| 1ce77cc14f | |||
| 4a9b969a9c | |||
| ece4a72e10 | |||
| ee26396c49 | |||
| 76c3ea15fb | |||
| ac4b07fde9 | |||
| b259c6a506 | |||
| 3a7eb3729c | |||
| 1c39e743d4 |
39 changed files with 16777 additions and 845 deletions
|
|
@ -1,5 +1,5 @@
|
|||
[build]
|
||||
rustc-wrapper = "sccache"
|
||||
# rustc-wrapper = "sccache"
|
||||
|
||||
[target.x86_64-unknown-linux-gnu]
|
||||
linker = "clang"
|
||||
|
|
|
|||
8
.env.example
Normal file
8
.env.example
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
# General Bots Environment Configuration
|
||||
# Copy this file to .env and fill in values
|
||||
# NEVER commit .env to version control
|
||||
|
||||
# Vault connection
|
||||
VAULT_ADDR=https://127.0.0.1:8200
|
||||
VAULT_TOKEN=<your-vault-token-here>
|
||||
VAULT_CACERT=./botserver-stack/vault/certs/ca.crt
|
||||
16
.forgejo/workflows/botapp.yaml
Normal file
16
.forgejo/workflows/botapp.yaml
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
name: Botapp CI
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
paths:
|
||||
- 'botapp/**'
|
||||
jobs:
|
||||
build:
|
||||
runs-on: gbo
|
||||
steps:
|
||||
- name: Build
|
||||
run: |
|
||||
cd /opt/gbo/work/botapp
|
||||
git reset --hard HEAD && git clean -fd
|
||||
git pull
|
||||
cargo build
|
||||
16
.forgejo/workflows/botbook.yaml
Normal file
16
.forgejo/workflows/botbook.yaml
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
name: Botbook CI
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
paths:
|
||||
- 'botbook/**'
|
||||
jobs:
|
||||
build:
|
||||
runs-on: gbo
|
||||
steps:
|
||||
- name: Build
|
||||
run: |
|
||||
cd /opt/gbo/work/botbook
|
||||
git reset --hard HEAD && git clean -fd
|
||||
git pull
|
||||
cargo build
|
||||
16
.forgejo/workflows/botdevice.yaml
Normal file
16
.forgejo/workflows/botdevice.yaml
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
name: Botdevice CI
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
paths:
|
||||
- 'botdevice/**'
|
||||
jobs:
|
||||
build:
|
||||
runs-on: gbo
|
||||
steps:
|
||||
- name: Build
|
||||
run: |
|
||||
cd /opt/gbo/work/botdevice
|
||||
git reset --hard HEAD && git clean -fd
|
||||
git pull
|
||||
cargo build
|
||||
16
.forgejo/workflows/botmodels.yaml
Normal file
16
.forgejo/workflows/botmodels.yaml
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
name: Botmodels CI
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
paths:
|
||||
- 'botmodels/**'
|
||||
jobs:
|
||||
build:
|
||||
runs-on: gbo
|
||||
steps:
|
||||
- name: Build
|
||||
run: |
|
||||
cd /opt/gbo/work/botmodels
|
||||
git reset --hard HEAD && git clean -fd
|
||||
git pull
|
||||
cargo build
|
||||
16
.forgejo/workflows/botplugin.yaml
Normal file
16
.forgejo/workflows/botplugin.yaml
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
name: Botplugin CI
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
paths:
|
||||
- 'botplugin/**'
|
||||
jobs:
|
||||
build:
|
||||
runs-on: gbo
|
||||
steps:
|
||||
- name: Build
|
||||
run: |
|
||||
cd /opt/gbo/work/botplugin
|
||||
git reset --hard HEAD && git clean -fd
|
||||
git pull
|
||||
cargo build
|
||||
29
.forgejo/workflows/botserver.yaml
Normal file
29
.forgejo/workflows/botserver.yaml
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
name: BotServer CI
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
paths:
|
||||
- 'botserver/**'
|
||||
- 'botlib/**'
|
||||
- 'Cargo.lock'
|
||||
- '.forgejo/workflows/botserver.yaml'
|
||||
jobs:
|
||||
build:
|
||||
runs-on: gbo
|
||||
steps:
|
||||
- name: Build
|
||||
run: |
|
||||
cd /opt/gbo/work/botserver
|
||||
git reset --hard HEAD && git clean -fd
|
||||
git pull
|
||||
git submodule update --init --recursive botlib botserver
|
||||
cargo build -p botserver
|
||||
- name: Deploy
|
||||
run: |
|
||||
sudo incus exec system -- systemctl stop botserver || true
|
||||
sudo incus exec system -- pkill -x botserver || true
|
||||
sleep 1
|
||||
sudo incus file push /opt/gbo/work/botserver/target/debug/botserver system:/opt/gbo/bin/botserver --mode=0755
|
||||
sudo incus exec system -- systemctl start botserver
|
||||
sleep 2
|
||||
sudo incus exec system -- pgrep -x botserver && echo "✅ BotServer Deployed" || echo "❌ Failed"
|
||||
16
.forgejo/workflows/bottest.yaml
Normal file
16
.forgejo/workflows/bottest.yaml
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
name: Bottest CI
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
paths:
|
||||
- 'bottest/**'
|
||||
jobs:
|
||||
build:
|
||||
runs-on: gbo
|
||||
steps:
|
||||
- name: Build
|
||||
run: |
|
||||
cd /opt/gbo/work/bottest
|
||||
git reset --hard HEAD && git clean -fd
|
||||
git pull
|
||||
cargo build
|
||||
20
.forgejo/workflows/botui.yaml
Normal file
20
.forgejo/workflows/botui.yaml
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
name: BotUI CI
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
paths:
|
||||
- 'botui/**'
|
||||
- 'botlib/**'
|
||||
jobs:
|
||||
build:
|
||||
runs-on: gbo
|
||||
steps:
|
||||
- name: Build
|
||||
run: |
|
||||
cd /opt/gbo/work/botui
|
||||
git reset --hard HEAD && git clean -fd
|
||||
git pull
|
||||
cargo build
|
||||
- name: Deploy
|
||||
run: |
|
||||
echo "BotUI deployed"
|
||||
66
.gitignore
vendored
66
.gitignore
vendored
|
|
@ -2,15 +2,23 @@
|
|||
target/
|
||||
*.out
|
||||
bin/
|
||||
|
||||
*.png
|
||||
*.jpg
|
||||
# Logs
|
||||
*.log
|
||||
*logfile*
|
||||
*-log*
|
||||
.vscode
|
||||
.zed
|
||||
.gemini
|
||||
.claude
|
||||
|
||||
|
||||
# Temporary files
|
||||
.tmp*
|
||||
.tmp/*
|
||||
.tmp
|
||||
|
||||
|
||||
# Environment files
|
||||
.env
|
||||
|
|
@ -24,13 +32,63 @@ work/
|
|||
|
||||
# Documentation build
|
||||
docs/book
|
||||
|
||||
.ruff_cache
|
||||
.goutputstream*
|
||||
# Installers (keep gitkeep)
|
||||
botserver-installers/*
|
||||
!botserver-installers/.gitkeep
|
||||
botserver-stack
|
||||
TODO*
|
||||
work
|
||||
.swp
|
||||
|
||||
# Lock file
|
||||
# Cargo.lock (should be tracked)
|
||||
.kiro
|
||||
config
|
||||
|
||||
# Lock file (regenerated from Cargo.toml)
|
||||
Cargo.lock
|
||||
# Data directory (contains bot configs and API keys)
|
||||
data/
|
||||
|
||||
# Playwright
|
||||
node_modules/
|
||||
/test-results/
|
||||
/playwright-report/
|
||||
/blob-report/
|
||||
/playwright/.cache/
|
||||
/playwright/.auth/
|
||||
.playwright*
|
||||
.ruff_cache
|
||||
.opencode
|
||||
config/directory_config.json
|
||||
# CI cache bust: Fri Feb 13 22:33:51 UTC 2026
|
||||
|
||||
# Secrets - NEVER commit these files
|
||||
vault-unseal-keys
|
||||
start-and-unseal.sh
|
||||
vault-token-*
|
||||
init.json
|
||||
*.pem
|
||||
*.key
|
||||
*.crt
|
||||
*.cert
|
||||
$null
|
||||
AppData/
|
||||
build_errors*.txt
|
||||
build_errors_utf8.txt
|
||||
check.json
|
||||
clippy*.txt
|
||||
errors.txt
|
||||
errors_utf8.txt
|
||||
|
||||
vault-unseal-keysdefault-vault.tar
|
||||
prompts/sec-bots.md
|
||||
AGENTS-PROD.md
|
||||
|
||||
# Backup files
|
||||
*.head
|
||||
*.bad2
|
||||
*.bad
|
||||
*.check
|
||||
*.fix
|
||||
*.bak
|
||||
|
|
|
|||
23
.gitmodules
vendored
23
.gitmodules
vendored
|
|
@ -1,42 +1,43 @@
|
|||
[submodule "botapp"]
|
||||
path = botapp
|
||||
url = https://github.com/GeneralBots/botapp.git
|
||||
url = ../botapp.git
|
||||
|
||||
[submodule "botserver"]
|
||||
path = botserver
|
||||
url = https://github.com/GeneralBots/botserver.git
|
||||
url = ../BotServer.git
|
||||
|
||||
[submodule "botlib"]
|
||||
path = botlib
|
||||
url = https://github.com/GeneralBots/botlib.git
|
||||
url = ../botlib.git
|
||||
|
||||
[submodule "botui"]
|
||||
path = botui
|
||||
url = https://github.com/GeneralBots/botui.git
|
||||
url = ../botui.git
|
||||
|
||||
[submodule "botbook"]
|
||||
path = botbook
|
||||
url = https://github.com/GeneralBots/botbook.git
|
||||
url = ../botbook.git
|
||||
|
||||
[submodule "bottest"]
|
||||
path = bottest
|
||||
url = https://github.com/GeneralBots/bottest.git
|
||||
url = ../bottest.git
|
||||
|
||||
[submodule "botdevice"]
|
||||
path = botdevice
|
||||
url = https://github.com/GeneralBots/botdevice.git
|
||||
url = ../botdevice.git
|
||||
|
||||
[submodule "botmodels"]
|
||||
path = botmodels
|
||||
url = https://github.com/GeneralBots/botmodels.git
|
||||
url = ../botmodels.git
|
||||
|
||||
[submodule "botplugin"]
|
||||
path = botplugin
|
||||
url = https://github.com/GeneralBots/botplugin.git
|
||||
url = ../botplugin.git
|
||||
|
||||
[submodule "bottemplates"]
|
||||
path = bottemplates
|
||||
url = https://github.com/GeneralBots/bottemplates.git
|
||||
url = ../bottemplates.git
|
||||
|
||||
[submodule ".github"]
|
||||
path = .github
|
||||
url = https://github.com/GeneralBots/.github.git
|
||||
url = ../.github.git
|
||||
|
|
|
|||
24
.vscode/launch.json
vendored
24
.vscode/launch.json
vendored
|
|
@ -1,24 +0,0 @@
|
|||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
|
||||
{
|
||||
"type": "lldb",
|
||||
"request": "launch",
|
||||
"name": "Debug executable 'botserver'",
|
||||
"cargo": {
|
||||
"args": ["run", "--bin=botserver", "--package=botserver", "--manifest-path=${workspaceFolder}/botserver/Cargo.toml"],
|
||||
"filter": {
|
||||
"name": "botserver",
|
||||
"kind": "bin"
|
||||
}
|
||||
},
|
||||
"args": [],
|
||||
"env": {
|
||||
"RUST_LOG": "trace,aws_sigv4=off,aws_smithy_checksums=off,mio=off,reqwest=off,aws_runtime=off,aws_smithy_http_client=off,rustls=off,hyper_util=off,aws_smithy_runtime=off,aws_smithy_runtime_api=off,tracing=off,aws_sdk_s3=off"
|
||||
|
||||
},
|
||||
"cwd": "${workspaceFolder}/botserver"
|
||||
},
|
||||
]
|
||||
}
|
||||
5
.vscode/settings.json
vendored
5
.vscode/settings.json
vendored
|
|
@ -1,5 +0,0 @@
|
|||
{
|
||||
"git.ignoreLimitWarning": true,
|
||||
"Codegeex.SidebarUI.LanguagePreference": "English",
|
||||
"Codegeex.RepoIndex": true
|
||||
}
|
||||
11680
Cargo.lock
generated
Normal file
11680
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -9,6 +9,7 @@ members = [
|
|||
"bottest",
|
||||
"botui",
|
||||
]
|
||||
exclude = ["backup-to-s3"]
|
||||
|
||||
[workspace.lints.rust]
|
||||
|
||||
|
|
@ -109,6 +110,7 @@ url = "2.5"
|
|||
dirs = "5.0"
|
||||
tempfile = "3"
|
||||
walkdir = "2.5.0"
|
||||
notify = "8.0"
|
||||
|
||||
# ─── COMPRESSION / ARCHIVES ───
|
||||
flate2 = "1.0"
|
||||
|
|
@ -174,7 +176,7 @@ indicatif = "0.18.0"
|
|||
|
||||
# ─── MEMORY ALLOCATOR ───
|
||||
tikv-jemallocator = "0.6"
|
||||
tikv-jemalloc-ctl = { version = "0.6", default-features = false }
|
||||
tikv-jemalloc-ctl = { version = "0.6", default-features = false, features = ["stats"] }
|
||||
|
||||
# ─── SECRETS / VAULT ───
|
||||
vaultrs = "0.7"
|
||||
|
|
@ -196,7 +198,7 @@ csv = "1.3"
|
|||
tonic = { version = "0.14.2", default-features = false }
|
||||
|
||||
# ─── STATIC FILES ───
|
||||
rust-embed = "8.5"
|
||||
rust-embed = { version = "8.5", features = ["interpolate-folder-path"] }
|
||||
mime_guess = "2.0"
|
||||
|
||||
# ─── TAURI (Desktop/Mobile) ───
|
||||
|
|
|
|||
|
|
@ -1,204 +0,0 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# DEPENDENCIES-DEV.sh - Development Dependencies for General Bots
|
||||
#
|
||||
# This script installs additional packages needed for BUILDING botserver from source.
|
||||
# Only install these if you plan to compile the code yourself.
|
||||
#
|
||||
# Usage: sudo ./DEPENDENCIES-DEV.sh
|
||||
#
|
||||
|
||||
set -e
|
||||
|
||||
# Colors
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m'
|
||||
|
||||
echo -e "${GREEN}========================================${NC}"
|
||||
echo -e "${GREEN} General Bots Development Dependencies${NC}"
|
||||
echo -e "${GREEN}========================================${NC}"
|
||||
|
||||
# Check root
|
||||
if [ "$EUID" -ne 0 ]; then
|
||||
echo -e "${RED}Error: Run as root (use sudo)${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Detect OS
|
||||
if [ -f /etc/os-release ]; then
|
||||
. /etc/os-release
|
||||
OS=$ID
|
||||
else
|
||||
echo -e "${RED}Error: Cannot detect OS${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo -e "${YELLOW}OS: $OS${NC}"
|
||||
|
||||
install_debian_ubuntu() {
|
||||
apt-get update
|
||||
apt-get install -y \
|
||||
build-essential \
|
||||
gcc \
|
||||
g++ \
|
||||
clang \
|
||||
llvm-dev \
|
||||
libclang-dev \
|
||||
cmake \
|
||||
make \
|
||||
git \
|
||||
pkg-config \
|
||||
libssl-dev \
|
||||
libpq-dev \
|
||||
liblzma-dev \
|
||||
zlib1g-dev \
|
||||
libabseil-dev \
|
||||
protobuf-compiler \
|
||||
libprotobuf-dev \
|
||||
automake \
|
||||
bison \
|
||||
flex \
|
||||
gperf \
|
||||
libtool \
|
||||
m4 \
|
||||
nasm \
|
||||
python3 \
|
||||
python3-pip \
|
||||
nodejs \
|
||||
npm
|
||||
|
||||
# Cross-compilation toolchains
|
||||
apt-get install -y \
|
||||
gcc-aarch64-linux-gnu \
|
||||
gcc-arm-linux-gnueabihf \
|
||||
gcc-x86-64-linux-gnu || true
|
||||
}
|
||||
|
||||
install_fedora_rhel() {
|
||||
dnf groupinstall -y "Development Tools"
|
||||
dnf install -y \
|
||||
gcc \
|
||||
gcc-c++ \
|
||||
clang \
|
||||
llvm-devel \
|
||||
clang-devel \
|
||||
cmake \
|
||||
make \
|
||||
git \
|
||||
pkgconf-devel \
|
||||
openssl-devel \
|
||||
libpq-devel \
|
||||
xz-devel \
|
||||
zlib-devel \
|
||||
abseil-cpp-devel \
|
||||
protobuf-compiler \
|
||||
protobuf-devel \
|
||||
automake \
|
||||
bison \
|
||||
flex \
|
||||
gperf \
|
||||
libtool \
|
||||
m4 \
|
||||
nasm \
|
||||
python3 \
|
||||
python3-pip \
|
||||
nodejs \
|
||||
npm
|
||||
}
|
||||
|
||||
install_arch() {
|
||||
pacman -Sy --noconfirm \
|
||||
base-devel \
|
||||
gcc \
|
||||
clang \
|
||||
llvm \
|
||||
cmake \
|
||||
make \
|
||||
git \
|
||||
pkgconf \
|
||||
openssl \
|
||||
postgresql-libs \
|
||||
xz \
|
||||
zlib \
|
||||
abseil-cpp \
|
||||
protobuf \
|
||||
automake \
|
||||
bison \
|
||||
flex \
|
||||
gperf \
|
||||
libtool \
|
||||
m4 \
|
||||
nasm \
|
||||
python \
|
||||
python-pip \
|
||||
nodejs \
|
||||
npm
|
||||
}
|
||||
|
||||
install_alpine() {
|
||||
apk add --no-cache \
|
||||
build-base \
|
||||
gcc \
|
||||
g++ \
|
||||
clang \
|
||||
llvm-dev \
|
||||
clang-dev \
|
||||
cmake \
|
||||
make \
|
||||
git \
|
||||
pkgconf-dev \
|
||||
openssl-dev \
|
||||
postgresql-dev \
|
||||
xz-dev \
|
||||
zlib-dev \
|
||||
abseil-cpp-dev \
|
||||
protobuf-dev \
|
||||
protoc \
|
||||
automake \
|
||||
bison \
|
||||
flex \
|
||||
gperf \
|
||||
libtool \
|
||||
m4 \
|
||||
nasm \
|
||||
python3 \
|
||||
py3-pip \
|
||||
nodejs \
|
||||
npm
|
||||
}
|
||||
|
||||
case $OS in
|
||||
ubuntu|debian|linuxmint|pop)
|
||||
install_debian_ubuntu
|
||||
;;
|
||||
fedora|rhel|centos|rocky|almalinux)
|
||||
install_fedora_rhel
|
||||
;;
|
||||
arch|manjaro)
|
||||
install_arch
|
||||
;;
|
||||
alpine)
|
||||
install_alpine
|
||||
;;
|
||||
*)
|
||||
echo -e "${RED}Unsupported OS: $OS${NC}"
|
||||
echo "Required development packages:"
|
||||
echo " - build-essential/base-devel"
|
||||
echo " - gcc, g++, clang"
|
||||
echo " - cmake, make, git"
|
||||
echo " - Development headers for:"
|
||||
echo " - OpenSSL, PostgreSQL, XZ, zlib"
|
||||
echo " - Abseil, Protobuf, LLVM"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
echo -e "${GREEN}Development dependencies installed!${NC}"
|
||||
echo ""
|
||||
echo "Install Rust if not already installed:"
|
||||
echo " curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh"
|
||||
echo ""
|
||||
echo "Then build with:"
|
||||
echo " cargo build --release"
|
||||
77
DEPENDENCIES.ps1
Normal file
77
DEPENDENCIES.ps1
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
<#
|
||||
.SYNOPSIS
|
||||
Installs runtime dependencies for General Bots on Windows.
|
||||
|
||||
.DESCRIPTION
|
||||
This script downloads and configures the system libraries required to build
|
||||
and run BotServer on Windows. It downloads PostgreSQL binaries (for libpq)
|
||||
and sets the PQ_LIB_DIR environment variable permanently.
|
||||
|
||||
.EXAMPLE
|
||||
PS> .\DEPENDENCIES.ps1
|
||||
#>
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
# ─── COLORS ───
|
||||
function Write-Step { param($msg) Write-Host " * $msg" -ForegroundColor Green }
|
||||
function Write-Warn { param($msg) Write-Host " ! $msg" -ForegroundColor Yellow }
|
||||
function Write-Err { param($msg) Write-Host " x $msg" -ForegroundColor Red }
|
||||
|
||||
Write-Host "========================================" -ForegroundColor Green
|
||||
Write-Host " General Bots Runtime Dependencies" -ForegroundColor Green
|
||||
Write-Host " (Windows)" -ForegroundColor Green
|
||||
Write-Host "========================================" -ForegroundColor Green
|
||||
Write-Host ""
|
||||
|
||||
# ─── PostgreSQL binaries (libpq.lib for Diesel ORM) ───
|
||||
$PgsqlDir = "C:\pgsql\pgsql"
|
||||
$PgsqlLib = "$PgsqlDir\lib\libpq.lib"
|
||||
$PgsqlZipUrl = "https://get.enterprisedb.com/postgresql/postgresql-17.4-1-windows-x64-binaries.zip"
|
||||
$PgsqlZip = "$env:TEMP\pgsql.zip"
|
||||
|
||||
if (Test-Path $PgsqlLib) {
|
||||
Write-Step "PostgreSQL binaries already present at $PgsqlDir"
|
||||
} else {
|
||||
Write-Host "`nDownloading PostgreSQL binaries..." -ForegroundColor Cyan
|
||||
Write-Host " URL: $PgsqlZipUrl"
|
||||
Write-Host " This may take a few minutes (~300MB)...`n"
|
||||
|
||||
Invoke-WebRequest -Uri $PgsqlZipUrl -OutFile $PgsqlZip -UseBasicParsing
|
||||
|
||||
Write-Host "Extracting to C:\pgsql ..."
|
||||
if (Test-Path "C:\pgsql") { Remove-Item "C:\pgsql" -Recurse -Force }
|
||||
Expand-Archive -Path $PgsqlZip -DestinationPath "C:\pgsql" -Force
|
||||
Remove-Item $PgsqlZip -Force -ErrorAction SilentlyContinue
|
||||
|
||||
if (Test-Path $PgsqlLib) {
|
||||
Write-Step "PostgreSQL binaries installed successfully."
|
||||
} else {
|
||||
Write-Err "Failed to find libpq.lib after extraction!"
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
|
||||
# Set PQ_LIB_DIR permanently for the current user
|
||||
$CurrentPqDir = [System.Environment]::GetEnvironmentVariable("PQ_LIB_DIR", "User")
|
||||
if ($CurrentPqDir -ne "$PgsqlDir\lib") {
|
||||
[System.Environment]::SetEnvironmentVariable("PQ_LIB_DIR", "$PgsqlDir\lib", "User")
|
||||
$env:PQ_LIB_DIR = "$PgsqlDir\lib"
|
||||
Write-Step "PQ_LIB_DIR set to '$PgsqlDir\lib' (User environment variable)"
|
||||
} else {
|
||||
Write-Step "PQ_LIB_DIR already configured."
|
||||
}
|
||||
|
||||
# ─── Summary ───
|
||||
Write-Host ""
|
||||
Write-Host "========================================" -ForegroundColor Green
|
||||
Write-Host " Dependencies installed!" -ForegroundColor Green
|
||||
Write-Host "========================================" -ForegroundColor Green
|
||||
Write-Host ""
|
||||
Write-Host "You can now build and run:" -ForegroundColor Cyan
|
||||
Write-Host " cargo build -p botserver"
|
||||
Write-Host " cargo build -p botui"
|
||||
Write-Host " .\restart.ps1"
|
||||
Write-Host ""
|
||||
Write-Host "NOTE: If this is the first time, restart your terminal" -ForegroundColor Yellow
|
||||
Write-Host " so PQ_LIB_DIR takes effect." -ForegroundColor Yellow
|
||||
245
DEPENDENCIES.sh
245
DEPENDENCIES.sh
|
|
@ -1,140 +1,133 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# DEPENDENCIES.sh - Runtime Dependencies for General Bots
|
||||
#
|
||||
# This script installs all system packages required to RUN botserver binary.
|
||||
# These are the minimal dependencies needed for production deployment.
|
||||
#
|
||||
# Usage: sudo ./DEPENDENCIES.sh
|
||||
#
|
||||
#!/bin/bash
|
||||
#
|
||||
# DEPENDENCIES.sh - Runtime Dependencies for General Bots
|
||||
#
|
||||
# This script installs all system packages required to RUN botserver binary.
|
||||
# These are the minimal dependencies needed for production deployment.
|
||||
#
|
||||
# Usage: sudo ./DEPENDENCIES.sh
|
||||
#
|
||||
|
||||
set -e
|
||||
set -e
|
||||
|
||||
# Colors
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m'
|
||||
# Colors
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
NC='\033[0m'
|
||||
|
||||
echo -e "${GREEN}========================================${NC}"
|
||||
echo -e "${GREEN} General Bots Runtime Dependencies${NC}"
|
||||
echo -e "${GREEN}========================================${NC}"
|
||||
echo -e "${GREEN}========================================${NC}"
|
||||
echo -e "${GREEN} General Bots Runtime Dependencies${NC}"
|
||||
echo -e "${GREEN}========================================${NC}"
|
||||
|
||||
# Check root
|
||||
if [ "$EUID" -ne 0 ]; then
|
||||
echo -e "${RED}Error: Run as root (use sudo)${NC}"
|
||||
exit 1
|
||||
fi
|
||||
# Check root
|
||||
if [ "$EUID" -ne 0 ]; then
|
||||
echo -e "${RED}Error: Run as root (use sudo)${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Detect OS
|
||||
if [ -f /etc/os-release ]; then
|
||||
. /etc/os-release
|
||||
OS=$ID
|
||||
else
|
||||
echo -e "${RED}Error: Cannot detect OS${NC}"
|
||||
exit 1
|
||||
fi
|
||||
# Detect OS
|
||||
if [ -f /etc/os-release ]; then
|
||||
. /etc/os-release
|
||||
OS=$ID
|
||||
else
|
||||
echo -e "${RED}Error: Cannot detect OS${NC}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo -e "${YELLOW}OS: $OS${NC}"
|
||||
echo -e "${YELLOW}OS: $OS${NC}"
|
||||
|
||||
install_debian_ubuntu() {
|
||||
apt-get update
|
||||
apt-get install -y \
|
||||
libpq5 \
|
||||
libssl3 \
|
||||
liblzma5 \
|
||||
zlib1g \
|
||||
ca-certificates \
|
||||
curl \
|
||||
wget \
|
||||
libabseil20210324 \
|
||||
libclang1 \
|
||||
pkg-config \
|
||||
snapd
|
||||
install_debian_ubuntu() {
|
||||
|
||||
# LXC for containers
|
||||
snap install lxd || apt-get install -y lxd || true
|
||||
apt-get install -y \
|
||||
libpq5 \
|
||||
libssl3 \
|
||||
liblzma5 \
|
||||
zlib1g \
|
||||
ca-certificates \
|
||||
curl \
|
||||
wget \
|
||||
libclang1 \
|
||||
pkg-config \
|
||||
snapd
|
||||
|
||||
# Initialize LXD
|
||||
if command -v lxd &> /dev/null && ! lxc list &> /dev/null 2>&1; then
|
||||
lxd init --auto || true
|
||||
fi
|
||||
}
|
||||
|
||||
install_fedora_rhel() {
|
||||
dnf install -y \
|
||||
libpq \
|
||||
openssl-libs \
|
||||
xz-libs \
|
||||
zlib \
|
||||
ca-certificates \
|
||||
curl \
|
||||
wget \
|
||||
abseil-cpp \
|
||||
clang-libs \
|
||||
pkgconf-pkg-config \
|
||||
lxc \
|
||||
lxc-templates
|
||||
}
|
||||
}
|
||||
|
||||
install_arch() {
|
||||
pacman -Sy --noconfirm \
|
||||
postgresql-libs \
|
||||
openssl \
|
||||
xz \
|
||||
zlib \
|
||||
ca-certificates \
|
||||
curl \
|
||||
wget \
|
||||
abseil-cpp \
|
||||
clang \
|
||||
pkgconf \
|
||||
lxc
|
||||
}
|
||||
install_fedora_rhel() {
|
||||
dnf install -y \
|
||||
libpq \
|
||||
openssl-libs \
|
||||
xz-libs \
|
||||
zlib \
|
||||
ca-certificates \
|
||||
curl \
|
||||
wget \
|
||||
abseil-cpp \
|
||||
clang-libs \
|
||||
pkgconf-pkg-config \
|
||||
lxc \
|
||||
lxc-templates
|
||||
}
|
||||
|
||||
install_alpine() {
|
||||
apk add --no-cache \
|
||||
libpq \
|
||||
openssl \
|
||||
xz-libs \
|
||||
zlib \
|
||||
ca-certificates \
|
||||
curl \
|
||||
wget \
|
||||
abseil-cpp \
|
||||
clang \
|
||||
pkgconf \
|
||||
lxc
|
||||
}
|
||||
install_arch() {
|
||||
pacman -Sy --noconfirm \
|
||||
postgresql-libs \
|
||||
openssl \
|
||||
xz \
|
||||
zlib \
|
||||
ca-certificates \
|
||||
curl \
|
||||
wget \
|
||||
abseil-cpp \
|
||||
clang \
|
||||
pkgconf \
|
||||
lxc
|
||||
}
|
||||
|
||||
case $OS in
|
||||
ubuntu|debian|linuxmint|pop)
|
||||
install_debian_ubuntu
|
||||
;;
|
||||
fedora|rhel|centos|rocky|almalinux)
|
||||
install_fedora_rhel
|
||||
;;
|
||||
arch|manjaro)
|
||||
install_arch
|
||||
;;
|
||||
alpine)
|
||||
install_alpine
|
||||
;;
|
||||
*)
|
||||
echo -e "${RED}Unsupported OS: $OS${NC}"
|
||||
echo "Required libraries:"
|
||||
echo " - libpq (PostgreSQL client)"
|
||||
echo " - libssl (OpenSSL)"
|
||||
echo " - liblzma (XZ compression)"
|
||||
echo " - zlib (compression)"
|
||||
echo " - abseil-cpp (Google Abseil)"
|
||||
echo " - clang (LLVM runtime)"
|
||||
echo " - LXC (containers)"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
install_alpine() {
|
||||
apk add --no-cache \
|
||||
libpq \
|
||||
openssl \
|
||||
xz-libs \
|
||||
zlib \
|
||||
ca-certificates \
|
||||
curl \
|
||||
wget \
|
||||
abseil-cpp \
|
||||
clang \
|
||||
pkgconf \
|
||||
lxc
|
||||
}
|
||||
|
||||
echo -e "${GREEN}Runtime dependencies installed!${NC}"
|
||||
echo ""
|
||||
echo "You can now run:"
|
||||
echo " ./botserver"
|
||||
case $OS in
|
||||
ubuntu|debian|linuxmint|pop)
|
||||
install_debian_ubuntu
|
||||
;;
|
||||
fedora|rhel|centos|rocky|almalinux)
|
||||
install_fedora_rhel
|
||||
;;
|
||||
arch|manjaro)
|
||||
install_arch
|
||||
;;
|
||||
alpine)
|
||||
install_alpine
|
||||
;;
|
||||
*)
|
||||
echo -e "${RED}Unsupported OS: $OS${NC}"
|
||||
echo "Required libraries:"
|
||||
echo " - libpq (PostgreSQL client)"
|
||||
echo " - libssl (OpenSSL)"
|
||||
echo " - liblzma (XZ compression)"
|
||||
echo " - zlib (compression)"
|
||||
echo " - abseil-cpp (Google Abseil)"
|
||||
echo " - clang (LLVM runtime)"
|
||||
echo " - LXC (containers)"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
echo -e "${GREEN}Runtime dependencies installed!${NC}"
|
||||
echo ""
|
||||
echo "You can now run:"
|
||||
echo " ./botserver"
|
||||
|
|
|
|||
967
PROD.md
Normal file
967
PROD.md
Normal file
|
|
@ -0,0 +1,967 @@
|
|||
# Production Environment Guide
|
||||
|
||||
## CRITICAL RULES — READ FIRST
|
||||
|
||||
NEVER INCLUDE HERE CREDENTIALS OR COMPANY INFORMATION, THIS IS COMPANY AGNOSTIC.
|
||||
|
||||
Always manage services with `systemctl` inside the `system` Incus container. Never run `/opt/gbo/bin/botserver` or `/opt/gbo/bin/botui` directly — they will fail because they won't load the `.env` file containing Vault credentials and paths. The correct commands are `sudo incus exec system -- systemctl start|stop|restart|status botserver` and the same for `ui`. Systemctl handles environment loading, auto-restart, logging, and dependencies.
|
||||
|
||||
Never push secrets (API keys, passwords, tokens) to git. Never commit `init.json` (it contains Vault unseal keys). All secrets must come from Vault — only `VAULT_*` variables are allowed in `.env`. Never deploy manually via scp or ssh; always use CI/CD. Always push all submodules (botserver, botui, botlib) before or alongside the main repo. Always ask before pushing to ALM.
|
||||
|
||||
---
|
||||
|
||||
## Infrastructure Overview
|
||||
|
||||
The host machine is accessed via `ssh user@<hostname>`, running Incus (an LXD fork) as hypervisor. All services run inside named Incus containers. You enter containers with `sudo incus exec <container> -- <command>` and list them with `sudo incus list`.
|
||||
|
||||
### Container Architecture
|
||||
|
||||
| Container | Service | Technology | Binary Path | Logs Path | Data Path | Notes |
|
||||
|-----------|---------|------------|-------------|-----------|-----------|-------|
|
||||
| **system** | BotServer + BotUI | Rust/Axum | `/opt/gbo/bin/botserver`<br>`/opt/gbo/bin/botui` | `/opt/gbo/logs/out.log`<br>`/opt/gbo/logs/err.log` | `/opt/gbo/work/` | Main API + UI proxy |
|
||||
| **tables** | PostgreSQL | PostgreSQL 15+ | `/usr/lib/postgresql/*/bin/postgres` | `/opt/gbo/logs/postgresql/` | `/opt/gbo/data/pgdata/` | Primary database |
|
||||
| **vault** | HashiCorp Vault | Vault | `/opt/gbo/bin/vault` | `/opt/gbo/logs/vault/` | `/opt/gbo/data/vault/` | Secrets management |
|
||||
| **cache** | Valkey | Valkey (Redis fork) | `/opt/gbo/bin/valkey-server` | `/opt/gbo/logs/valkey/` | `/opt/gbo/data/valkey/` | Distributed cache |
|
||||
| **drive** | MinIO | MinIO | `/opt/gbo/bin/minio` | `/opt/gbo/logs/minio/` | `/opt/gbo/data/minio/` | Object storage (S3 API) |
|
||||
| **directory** | Zitadel | Zitadel (Go) | `/opt/gbo/bin/zitadel` | `/opt/gbo/logs/zitadel.log` | `PROD-DIRECTORY` DB | Identity provider |
|
||||
| **llm** | llama.cpp | C++/CUDA | `/opt/gbo/bin/llama-server` | `/opt/gbo/logs/llm/` | `/opt/gbo/models/` | Local LLM inference |
|
||||
| **vectordb** | Qdrant | Qdrant (Rust) | `/opt/gbo/bin/qdrant` | `/opt/gbo/logs/qdrant/` | `/opt/gbo/data/qdrant/` | Vector database |
|
||||
| **alm** | Forgejo | Forgejo (Go) | `/opt/gbo/bin/forgejo` | `/opt/gbo/logs/forgejo/` | `/opt/gbo/data/forgejo/` | Git server (port 4747) |
|
||||
| **alm-ci** | Forgejo Runner | Docker/runner | `/opt/gbo/bin/forgejo-runner` | `/opt/gbo/logs/forgejo-runner.log` | `/opt/gbo/data/ci/` | CI/CD runner |
|
||||
| **proxy** | Caddy | Caddy | `/opt/gbo/bin/caddy` | `/opt/gbo/logs/caddy/` | `/opt/gbo/conf/` | Reverse proxy |
|
||||
| **email** | Stalwart | Stalwart (Rust) | `/opt/gbo/bin/stalwart` | `/opt/gbo/logs/email/` | `/opt/gbo/data/email/` | Mail server |
|
||||
| **webmail** | Roundcube | PHP | `/usr/share/roundcube/` | `/var/log/php/` | `/var/lib/roundcube/` | Webmail frontend |
|
||||
| **dns** | CoreDNS | CoreDNS (Go) | `/opt/gbo/bin/coredns` | `/opt/gbo/logs/dns/` | `/opt/gbo/conf/Corefile` | DNS resolution |
|
||||
| **meet** | LiveKit | LiveKit (Go) | `/opt/gbo/bin/livekit-server` | `/opt/gbo/logs/meet/` | `/opt/gbo/data/meet/` | Video conferencing |
|
||||
| **table-editor** | NocoDB | NocoDB | `/opt/gbo/bin/nocodb` | `/opt/gbo/logs/nocodb/` | `/opt/gbo/data/nocodb/` | Database UI |
|
||||
|
||||
### Network Access
|
||||
|
||||
Externally, services are exposed via reverse proxy (Caddy). Internally, containers communicate via private IPs:
|
||||
|
||||
| Service | External URL | Internal Address |
|
||||
|---------|--------------|------------------|
|
||||
| BotServer | `https://<system-domain>` | `http://<system-ip>:8080` |
|
||||
| BotUI | `https://<chat-domain>` | `http://<system-ip>:3000` |
|
||||
| Zitadel | `https://<login-domain>` | `http://<directory-ip>:8080` |
|
||||
| Forgejo | `https://<alm-domain>` | `http://<alm-ip>:4747` |
|
||||
| Webmail | `https://<webmail-domain>` | `http://<webmail-ip>:80` |
|
||||
| Roundcube | `https://<roundcube-domain>` | `http://<webmail-ip>:80` |
|
||||
|
||||
**Note:** BotUI's `BOTSERVER_URL` must be `http://<system-ip>:8080` internally, NOT the external HTTPS URL.
|
||||
|
||||
---
|
||||
|
||||
## Daily Operations
|
||||
|
||||
### Daily Health Check (5 minutes)
|
||||
|
||||
Run this every morning or after any deploy:
|
||||
|
||||
```bash
|
||||
# 1. Container status
|
||||
sudo incus list
|
||||
|
||||
# 2. Service health - all should show "active (running)"
|
||||
sudo incus exec system -- systemctl is-active botserver
|
||||
sudo incus exec system -- systemctl is-active ui
|
||||
sudo incus exec directory -- systemctl is-active directory 2>/dev/null || echo "Directory check failed"
|
||||
sudo incus exec drive -- pgrep -f minio > /dev/null && echo "MinIO OK" || echo "MinIO DOWN"
|
||||
sudo incus exec tables -- pgrep -f postgres > /dev/null && echo "PostgreSQL OK" || echo "PostgreSQL DOWN"
|
||||
|
||||
# 3. IPv4 connectivity check - all containers should have IPv4
|
||||
sudo incus list -c n4 | grep -E "(system|tables|vault|directory|drive|cache|llm|vector_db)" | grep -v "10\." && echo "WARNING: Missing IPv4" || echo "IPv4 OK"
|
||||
|
||||
# 4. Application health endpoint
|
||||
curl -sf https://<system-domain>/api/health && echo "Health OK" || echo "Health FAILED"
|
||||
|
||||
# 5. Recent errors (last 10 lines)
|
||||
sudo incus exec system -- tail -10 /opt/gbo/logs/err.log | grep -i "error\|panic\|failed" | head -5
|
||||
```
|
||||
|
||||
**Expected Result:** All services "active", all containers have IPv4, health endpoint returns 200, no critical errors.
|
||||
|
||||
### Weekly Deep Check (15 minutes)
|
||||
|
||||
Run every Monday morning:
|
||||
|
||||
```bash
|
||||
# 1. Disk space on all containers
|
||||
for c in system tables vault directory drive cache llm vector_db; do
|
||||
echo "=== $c ==="
|
||||
sudo incus exec $c -- df -h / 2>/dev/null | tail -1
|
||||
done
|
||||
|
||||
# 2. Database connection pool status
|
||||
sudo incus exec tables -- psql -h localhost -U postgres -d botserver -c "SELECT count(*), state FROM pg_stat_activity GROUP BY state;"
|
||||
|
||||
# 3. Vault status (should be unsealed)
|
||||
sudo incus exec vault -- curl -ksf https://localhost:8200/v1/sys/health | grep -q '"sealed":false' && echo "Vault unsealed" || echo "Vault SEALED - CRITICAL"
|
||||
|
||||
# 4. CI runner status
|
||||
sudo incus exec alm-ci -- pgrep -f forgejo > /dev/null && echo "CI runner OK" || echo "CI runner DOWN"
|
||||
|
||||
# 5. MinIO buckets health
|
||||
sudo incus exec drive -- bash -c 'export PATH=/opt/gbo/bin:$PATH && mc admin info local' 2>&1 | head -10
|
||||
|
||||
# 6. Backup verification - check latest snapshot exists
|
||||
sudo incus snapshot list system | head -5
|
||||
```
|
||||
|
||||
### Quick Status Dashboard
|
||||
|
||||
One-line status of everything:
|
||||
|
||||
```bash
|
||||
echo "=== GBO Status Dashboard $(date) ==="
|
||||
echo "Containers:"
|
||||
sudo incus list -c n4,s | grep -E "(system|tables|vault|directory|drive|cache|llm|vector_db|alm-ci)" | awk '{print $1 ": " $3 " " $4}'
|
||||
echo ""
|
||||
echo "Services:"
|
||||
for svc in botserver ui; do
|
||||
sudo incus exec system -- systemctl is-active $svc 2>/dev/null && echo " $svc: ACTIVE" || echo " $svc: DOWN"
|
||||
done
|
||||
echo ""
|
||||
echo "Health:"
|
||||
curl -s -o /dev/null -w "%{http_code}" https://<system-domain>/api/health 2>/dev/null | grep -q "200" && echo " API: OK" || echo " API: FAIL"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Alert Response Playbook
|
||||
|
||||
### Alert: "No IPv4 on container"
|
||||
|
||||
**Symptoms:** Container shows empty IPV4 column in `incus list`
|
||||
|
||||
**Quick Fix:**
|
||||
```bash
|
||||
# Identify container
|
||||
CONTAINER=<name>
|
||||
IP=<unused-ip-in-range> # e.g., 10.x.x.x
|
||||
GATEWAY=<gateway-ip>
|
||||
|
||||
# Set static IP
|
||||
sudo incus config device set $CONTAINER eth0 ipv4.address $IP
|
||||
|
||||
# Configure network inside
|
||||
sudo incus exec $CONTAINER -- bash -c "cat > /etc/network/interfaces << 'EOF'
|
||||
auto lo
|
||||
iface lo inet loopback
|
||||
|
||||
auto eth0
|
||||
iface eth0 inet static
|
||||
address $IP
|
||||
netmask 255.255.255.0
|
||||
gateway $GATEWAY
|
||||
dns-nameservers 8.8.8.8 8.8.4.4
|
||||
EOF"
|
||||
|
||||
# Restart
|
||||
sudo incus restart $CONTAINER
|
||||
|
||||
# Verify
|
||||
sudo incus exec $CONTAINER -- ip addr show eth0
|
||||
```
|
||||
|
||||
**Prevention:** Always configure static IP when creating new containers.
|
||||
|
||||
---
|
||||
|
||||
### Alert: "ALM botserver problem" / CI Build Failed
|
||||
|
||||
**Symptoms:** Deploy not working, CI status shows failure
|
||||
|
||||
**Quick Diagnostics:**
|
||||
```bash
|
||||
# Check CI database for recent runs
|
||||
sudo incus exec tables -- bash -c 'export PGPASSWORD=<password>; psql -h localhost -U postgres -d PROD-ALM -c "SELECT id, status, created FROM action_run ORDER BY id DESC LIMIT 5;"'
|
||||
# Status codes: 0=pending, 1=success, 2=failure, 3=cancelled, 6=running
|
||||
```
|
||||
|
||||
**Quick Fixes:**
|
||||
|
||||
1. **If stuck at status 6 (running):**
|
||||
```bash
|
||||
RUN_ID=<stuck-run-id>
|
||||
sudo incus exec tables -- bash -c "export PGPASSWORD=<password>; psql -h localhost -U postgres -d PROD-ALM -c \"UPDATE action_task SET status = 0 WHERE id = $RUN_ID; UPDATE action_run_job SET status = 0 WHERE run_id = $RUN_ID; UPDATE action_run SET status = 0 WHERE id = $RUN_ID;\""
|
||||
```
|
||||
|
||||
2. **If /tmp permission denied:**
|
||||
```bash
|
||||
sudo incus exec alm-ci -- chmod 1777 /tmp
|
||||
sudo incus exec alm-ci -- touch /tmp/build.log && chmod 666 /tmp/build.log
|
||||
```
|
||||
|
||||
3. **If CI runner down:**
|
||||
```bash
|
||||
sudo incus exec alm-ci -- pkill -9 forgejo
|
||||
sleep 2
|
||||
sudo incus exec alm-ci -- bash -c 'cd /opt/gbo/bin && nohup ./forgejo-runner daemon --config config.yaml >> /opt/gbo/logs/forgejo-runner.log 2>&1 &'
|
||||
```
|
||||
|
||||
**After fix:** Push a trivial change to re-trigger CI.
|
||||
|
||||
---
|
||||
|
||||
### Alert: "Email container stopping reach Internet"
|
||||
|
||||
**Symptoms:** Email notifications failing, container cannot resolve external domains
|
||||
|
||||
**Quick Diagnostics:**
|
||||
```bash
|
||||
# Test DNS from email container
|
||||
sudo incus exec email -- nslookup google.com
|
||||
|
||||
# Check network config
|
||||
sudo incus exec email -- cat /etc/resolv.conf
|
||||
sudo incus exec email -- ip route
|
||||
```
|
||||
|
||||
**Quick Fixes:**
|
||||
|
||||
1. **If IPv6-only (no IPv4):** Follow "No IPv4 on container" playbook above.
|
||||
|
||||
2. **If DNS not working:**
|
||||
```bash
|
||||
# Force Google DNS
|
||||
sudo incus exec email -- bash -c 'echo "nameserver 8.8.8.8" > /etc/resolv.conf'
|
||||
|
||||
# Or configure via interfaces file
|
||||
sudo incus exec email -- bash -c "cat > /etc/network/interfaces << 'EOF'
|
||||
auto lo
|
||||
iface lo inet loopback
|
||||
|
||||
auto eth0
|
||||
iface eth0 inet static
|
||||
address <email-container-ip>
|
||||
netmask 255.255.255.0
|
||||
gateway <gateway>
|
||||
dns-nameservers 8.8.8.8 8.8.4.4
|
||||
EOF"
|
||||
sudo incus restart email
|
||||
```
|
||||
|
||||
3. **If firewall blocking:** Check iptables rules on host for email container IP.
|
||||
|
||||
---
|
||||
|
||||
### Alert: "Vault sealed"
|
||||
|
||||
**Symptoms:** All services failing, Vault health shows "sealed": true
|
||||
|
||||
**Quick Fix:**
|
||||
```bash
|
||||
# Get unseal keys from secure location (not in git!)
|
||||
KEY1=<key-from-secure-location>
|
||||
KEY2=<key-from-secure-location>
|
||||
KEY3=<key-from-secure-location>
|
||||
|
||||
sudo incus exec vault -- vault operator unseal $KEY1
|
||||
sudo incus exec vault -- vault operator unseal $KEY2
|
||||
sudo incus exec vault -- vault operator unseal $KEY3
|
||||
|
||||
# Verify
|
||||
sudo incus exec vault -- vault status
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Alert: "Botserver not responding"
|
||||
|
||||
**Quick Diagnostics:**
|
||||
```bash
|
||||
# Check process
|
||||
sudo incus exec system -- pgrep -f botserver || echo "NOT RUNNING"
|
||||
|
||||
# Check systemd status
|
||||
sudo incus exec system -- systemctl status botserver --no-pager
|
||||
|
||||
# Check recent logs
|
||||
sudo incus exec system -- tail -20 /opt/gbo/logs/err.log
|
||||
|
||||
# Check for GLIBC errors
|
||||
sudo incus exec system -- ldd /opt/gbo/bin/botserver | grep "not found"
|
||||
```
|
||||
|
||||
**Quick Fixes:**
|
||||
|
||||
1. **If systemd failed:**
|
||||
```bash
|
||||
sudo incus exec system -- systemctl restart botserver
|
||||
sudo incus exec system -- systemctl restart ui
|
||||
```
|
||||
|
||||
2. **If GLIBC mismatch:** Binary compiled with wrong glibc. Must rebuild inside system container (Debian 12, glibc 2.36).
|
||||
|
||||
3. **If port conflict:**
|
||||
```bash
|
||||
sudo incus exec system -- lsof -i :8080
|
||||
sudo incus exec system -- killall botserver
|
||||
sudo incus exec system -- systemctl start botserver
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Services Detail
|
||||
|
||||
Botserver runs as user `gbuser`, binary at `/opt/gbo/bin/botserver`, logs at `/opt/gbo/logs/out.log` and `/opt/gbo/logs/err.log`, systemd unit at `/etc/systemd/system/botserver.service`, env loaded from `/opt/gbo/bin/.env`. Bot BASIC scripts are stored in MinIO Drive under `{bot}.gbai/{bot}.gbdialog/*.bas` and are downloaded/compiled by DriveMonitor to `/opt/gbo/work/{bot}.gbai/{bot}.gbdialog/*.ast`.
|
||||
|
||||
The directory service runs Zitadel as user `root`, binary at `/opt/gbo/bin/zitadel`, logs at `/opt/gbo/logs/zitadel.log`, systemd unit at `/etc/systemd/system/directory.service`, and loads environment from the service configuration. Zitadel provides identity management and OAuth2 services for the platform.
|
||||
|
||||
Internally, Zitadel listens on port 8080 within the directory container. For external access:
|
||||
- Via public domain (HTTPS): `https://<login-domain>` (configured through proxy container)
|
||||
- Via host IP (HTTP): `http://<host-ip>:9000` (direct container port forwarding)
|
||||
- Via container IP (HTTP): `http://<directory-container-ip>:9000` (direct container access)
|
||||
|
||||
Access the Zitadel console at `https://<login-domain>/ui/console` with admin credentials. Zitadel implements v1 Management API (deprecated) and v2 Organization/User services. Always use the v2 endpoints under `/v2/organizations` and `/v2/users` for all operations.
|
||||
|
||||
The botserver bootstrap also manages: Vault (secrets), PostgreSQL (database), Valkey (cache, password auth), MinIO (object storage), Zitadel (identity provider), and llama.cpp (LLM).
|
||||
|
||||
To obtain a PAT for Zitadel API access, check /opt/gbo/conf/directory/admin-pat.txt in the directory container. Use it with curl by setting the Authorization header: `Authorization: Bearer $(cat /opt/gbo/conf/directory/admin-pat.txt)` and include `-H "Host: <directory-ip> "` for correct host resolution.
|
||||
|
||||
---
|
||||
|
||||
## Directory Management (Zitadel)
|
||||
|
||||
### Getting Admin PAT (Personal Access Token)
|
||||
|
||||
```bash
|
||||
# Get the admin PAT from directory container
|
||||
PAT=$(ssh administrator@<hostname> "sudo incus exec directory -- cat /opt/gbo/conf/directory/admin-pat.txt")
|
||||
```
|
||||
|
||||
### User Management via API (v2)
|
||||
|
||||
**Create a Human User:**
|
||||
```bash
|
||||
curl -X POST "http://<directory-ip>:8080/v2/users/human" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Authorization: Bearer $PAT" \
|
||||
-H "Host: <directory-ip>" \
|
||||
-d '{
|
||||
"username": "testuser",
|
||||
"profile": {"givenName": "Test", "familyName": "User"},
|
||||
"email": {"email": "test@example.com", "isVerified": true},
|
||||
"password": {"password": "<password>", "changeRequired": false}
|
||||
}'
|
||||
```
|
||||
|
||||
**List Users:**
|
||||
```bash
|
||||
curl -X POST "http://<directory-ip>:8080/v2/users" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Authorization: Bearer $PAT" \
|
||||
-H "Host: <directory-ip>" \
|
||||
-d '{"query": {"offset": 0, "limit": 100}}'
|
||||
```
|
||||
|
||||
**Update User Password:**
|
||||
```bash
|
||||
curl -X POST "http://<directory-ip>:8080/v2/users/<user-id>/password" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Authorization: Bearer $PAT" \
|
||||
-H "Host: <directory-ip>" \
|
||||
-d '{
|
||||
"newPassword": {"password": "<password>", "changeRequired": false}
|
||||
}'
|
||||
```
|
||||
|
||||
**Delete User:**
|
||||
```bash
|
||||
curl -X DELETE "http://<directory-ip>:8080/v2/users/<user-id>" \
|
||||
-H "Authorization: Bearer $PAT" \
|
||||
-H "Host: <directory-ip>"
|
||||
```
|
||||
|
||||
### Directory Quick Reference
|
||||
|
||||
| Task | Command |
|
||||
|------|---------|
|
||||
| Get PAT | `sudo incus exec directory -- cat /opt/gbo/conf/directory/admin-pat.txt` |
|
||||
| Check health | `curl -sf http://<directory-ip>:8080/debug/healthz` |
|
||||
| Console UI | `http://<host-ip>:9000/ui/console` |
|
||||
| Create user | `POST /v2/users/human` |
|
||||
| List users | `POST /v2/users` |
|
||||
| Update password | `POST /v2/users/{id}/password` |
|
||||
|
||||
# /tmp permission denied for build.log
|
||||
sudo incus exec alm-ci -- chmod 1777 /tmp
|
||||
sudo incus exec alm-ci -- touch /tmp/build.log && chmod 666 /tmp/build.log
|
||||
|
||||
# Clean old CI runs (keep recent)
|
||||
sudo incus exec tables -- bash -c 'export PGPASSWORD=<postgres-password>; psql -h localhost -U postgres -d PROD-ALM -c "DELETE FROM action_run WHERE id < <RECENT_ID>;"'
|
||||
sudo incus exec tables -- bash -c 'export PGPASSWORD=<postgres-password>; psql -h localhost -U postgres -d PROD-ALM -c "DELETE FROM action_run_job WHERE run_id < <RECENT_ID>;"'
|
||||
```
|
||||
|
||||
**Watch CI in real-time:**
|
||||
```bash
|
||||
# Tail runner logs
|
||||
sudo incus exec alm-ci -- tail -f /opt/gbo/logs/forgejo-runner.log
|
||||
|
||||
# Check if new builds appear
|
||||
watch -n 5 'sudo incus exec tables -- bash -c "export PGPASSWORD=<postgres-password>; psql -h localhost -U postgres -d PROD-ALM -c \\"SELECT id, status, created FROM action_run ORDER BY id DESC LIMIT 3;\\""'
|
||||
|
||||
# Verify botserver deployed correctly
|
||||
sudo incus exec system -- /opt/gbo/bin/botserver --version 2>&1 | head -3
|
||||
sudo incus exec system -- tail -5 /opt/gbo/logs/err.log
|
||||
```
|
||||
|
||||
### Monitor CI/CD Build Status
|
||||
|
||||
**Check latest build status:**
|
||||
```bash
|
||||
# View latest 3 builds with status
|
||||
sudo incus exec alm -- bash -c 'cd /opt/gbo/data/GeneralBots/BotServer/actions/runs && for dir in $(ls -t | head -3); do echo "=== Build $dir ==="; cat $dir/jobs/0.json 2>/dev/null | grep -E "\"status\"|\"commit\"|\"workflow\"" | head -5; done'
|
||||
|
||||
# Watch runner logs in real-time
|
||||
sudo incus exec alm-ci -- tail -f /opt/gbo/logs/forgejo-runner.log | grep -E "Clone|Build|Deploy|Success|Failure"
|
||||
```
|
||||
|
||||
**Understand build timing:**
|
||||
- **Rust compilation**: 2-5 minutes (cold build), 30-60 seconds (incremental)
|
||||
- **Dependencies**: First build downloads ~200 dependencies
|
||||
- **Deploy step**: ~5 seconds
|
||||
- **Total CI time**: 2-6 minutes depending on cache
|
||||
|
||||
**Verify binary was updated:**
|
||||
```bash
|
||||
# Check binary timestamp
|
||||
ssh administrator@63.141.255.9 "sudo incus exec system -- stat -c '%y' /opt/gbo/bin/botserver"
|
||||
|
||||
# Check running version
|
||||
ssh administrator@63.141.255.9 "sudo incus exec system -- /opt/gbo/bin/botserver --version"
|
||||
|
||||
# Check health endpoint
|
||||
curl -sf https://chat.pragmatismo.com.br/api/health || echo "Health check failed"
|
||||
```
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## DriveMonitor & Bot Configuration
|
||||
|
||||
DriveMonitor is a background service inside botserver that watches MinIO buckets and syncs changes to the local filesystem and database every 10 seconds. It monitors three directory types per bot: the `.gbdialog/` folder for BASIC scripts (downloads and recompiles on change), the `.gbot/` folder for `config.csv` (syncs to the `bot_configuration` database table), and the `.gbkb/` folder for knowledge base documents (downloads and indexes for vector search).
|
||||
|
||||
Bot configuration is stored in two PostgreSQL tables inside the `botserver` database. The `bot_configuration` table holds key-value pairs with columns `bot_id`, `config_key`, `config_value`, `config_type`, `is_encrypted`, and `updated_at`. The `gbot_config_sync` table tracks sync state with columns `bot_id`, `config_file_path`, `last_sync_at`, `file_hash`, and `sync_count`.
|
||||
|
||||
The `config.csv` format is a plain CSV with no header: each line is `key,value`, for example `llm-provider,groq` or `theme-color1,#cc0000`. DriveMonitor syncs it when the file ETag changes in MinIO, on botserver startup, or after a restart.
|
||||
|
||||
**Check config status:** Query `bot_configuration` via `sudo incus exec tables -- psql -h localhost -U postgres -d botserver -c "SELECT config_key, config_value FROM bot_configuration WHERE bot_id = (SELECT id FROM bots WHERE name = '<botname>') ORDER BY config_key;"`. Check sync state via the `gbot_config_sync` table. Inspect the bucket directly with `sudo incus exec drive -- /opt/gbo/bin/mc cat local/<botname>.gbai/<botname>.gbot/config.csv`.
|
||||
|
||||
**Debug DriveMonitor:** Monitor live logs with `sudo incus exec system -- tail -f /opt/gbo/logs/out.log | grep -E "(DRIVE_MONITOR|check_gbot|config)"`. An empty `gbot_config_sync` table means DriveMonitor has not synced yet. If no new log entries appear after 30 seconds, the loop may be stuck — restart botserver with systemctl to clear the state.
|
||||
|
||||
**Common config issues:** If config.csv is missing from the bucket, create and upload it with `mc cp`. If the database shows stale values, restart botserver to force a fresh sync, or as a temporary fix update the database directly with `UPDATE bot_configuration SET config_value = 'groq', updated_at = NOW() WHERE ...`. To force a re-sync without restarting, copy config.csv over itself with `mc cp local/... local/...` to change the ETag.
|
||||
|
||||
---
|
||||
|
||||
## MinIO (Drive) Operations
|
||||
|
||||
All bot files live in MinIO buckets. Use the `mc` CLI at `/opt/gbo/bin/mc` from inside the `drive` container. The bucket structure per bot is: `{bot}.gbai/` as root, `{bot}.gbai/{bot}.gbdialog/` for BASIC scripts, `{bot}.gbai/{bot}.gbot/` for config.csv, and `{bot}.gbai/{bot}.gbkb/` for knowledge base folders.
|
||||
|
||||
Common mc commands: `mc ls local/` lists all buckets; `mc ls local/botname.gbai/` lists a bucket; `mc cat local/.../start.bas` prints a file; `mc cp local/.../file /tmp/file` downloads; `mc cp /tmp/file local/.../file` uploads (this triggers DriveMonitor recompile); `mc stat local/.../config.csv` shows ETag and metadata; `mc mb local/newbot.gbai` creates a bucket; `mc rb local/oldbot.gbai` removes an empty bucket.
|
||||
|
||||
If mc is not found, use the full path `/opt/gbo/bin/mc`. If alias `local` is not configured, check with `mc config host list`. If MinIO is not running, check with `sudo incus exec drive -- systemctl status minio`.
|
||||
|
||||
---
|
||||
|
||||
## Vault Security Architecture
|
||||
|
||||
HashiCorp Vault is the single source of truth for all secrets. Botserver reads `VAULT_ADDR` and `VAULT_TOKEN` from `/opt/gbo/bin/.env` at startup, initializes a TLS/mTLS client, then reads credentials from Vault paths. If Vault is unavailable, it falls back to defaults. The `.env` file must only contain `VAULT_*` variables plus `PORT`, `DATA_DIR`, `WORK_DIR`, and `LOAD_ONLY`.
|
||||
|
||||
**Global Vault paths:** `gbo/tables` holds PostgreSQL credentials; `gbo/drive` holds MinIO access key and secret; `gbo/cache` holds Valkey password; `gbo/llm` holds LLM URL and API keys; `gbo/directory` holds Zitadel config; `gbo/email` holds SMTP credentials; `gbo/vectordb` holds Qdrant config; `gbo/jwt` holds JWT signing secret; `gbo/encryption` holds the master encryption key. Organization-scoped secrets follow patterns like `gbo/orgs/{org_id}/bots/{bot_id}` and tenant infrastructure uses `gbo/tenants/{tenant_id}/infrastructure`.
|
||||
|
||||
**Credential resolution:** For any service, botserver checks the most specific Vault path first (org+bot level), falls back to a default bot path, then falls back to the global path, and only uses environment variables as a last resort in development.
|
||||
|
||||
**Verify Vault health:** `sudo incus exec vault -- curl -k -sf https://localhost:8200/v1/sys/health` should return JSON with `"sealed":false`. To read a secret: set `VAULT_ADDR`, `VAULT_TOKEN`, and `VAULT_CACERT` then run `vault kv get secret/gbo/tables`. To test from the system container, use curl with `--cacert /opt/gbo/conf/system/certificates/ca/ca.crt` and `-H "X-Vault-Token: <token>"`.
|
||||
|
||||
**init.json** is stored at `/opt/gbo/bin/botserver-stack/conf/vault/vault-conf/init.json` and contains the root token and 5 unseal keys (3 needed to unseal). Never commit this file to git. Store it encrypted in a secure location.
|
||||
|
||||
**Vault troubleshooting — cannot connect:** Check that the vault container's systemd unit is running, verify the token in `.env` is not expired with `vault token lookup`, confirm the CA cert path in `.env` matches the actual file location, and test network connectivity from system to vault container. To generate a new token: `vault token create -policy="botserver" -ttl="8760h" -format=json` then update `.env` and restart botserver.
|
||||
|
||||
**Get database credentials from Vault v2 API:**
|
||||
```bash
|
||||
ssh user@<hostname> "sudo incus exec system -- curl -s --cacert /opt/gbo/conf/system/certificates/ca/ca.crt -H 'X-Vault-Token: <vault-token>' https://<vault-ip>:8200/v1/secret/data/gbo/tables 2>/dev/null"
|
||||
```
|
||||
|
||||
**Vault troubleshooting — secrets missing:** Run `vault kv get secret/gbo/tables` (and other paths) to check if secrets exist. If a path returns NOT FOUND, add secrets with `vault kv put secret/gbo/tables host=<ip> port=5432 database=botserver username=gbuser password=<pw>` and similar for other paths.
|
||||
|
||||
**Vault sealed after restart:** Run `vault operator unseal <key1>`, repeat with key2 and key3 (3 of 5 keys from init.json), then verify with `vault status`.
|
||||
|
||||
**TLS certificate errors:** Confirm `/opt/gbo/conf/system/certificates/ca/ca.crt` exists in the system container. If missing, copy it from the vault container using `incus file pull vault/opt/gbo/conf/vault/ca.crt /tmp/ca.crt` then place it at the expected path.
|
||||
|
||||
**Vault snapshots:** Stop vault, run `sudo incus snapshot create vault backup-$(date +%Y%m%d-%H%M)`, start vault. Restore with `sudo incus snapshot restore vault <name>` while vault is stopped.
|
||||
|
||||
---
|
||||
|
||||
## DNS Management
|
||||
|
||||
### Updating DNS Records
|
||||
|
||||
**CRITICAL:** When updating DNS zone files, you MUST:
|
||||
|
||||
1. **Update the serial number** in the SOA record (format: YYYYMMDDNN)
|
||||
2. **Run sync-zones.sh** to propagate changes to secondary nameservers
|
||||
3. **Anonymize IPs and credentials** in all documentation and logs
|
||||
|
||||
**Workflow:**
|
||||
```bash
|
||||
# 1. Edit zone file
|
||||
sudo incus exec dns -- nano /opt/gbo/data/pragmatismo.com.br.zone
|
||||
|
||||
# 2. Update serial (YYYYMMDDNN format)
|
||||
# Example: 2026041801 (April 18, 2026, change #1)
|
||||
sudo incus exec dns -- sed -i 's/2026041801/2026041802/' /opt/gbo/data/pragmatismo.com.br.zone
|
||||
|
||||
# 3. Reload CoreDNS
|
||||
sudo incus exec dns -- pkill -HUP coredns
|
||||
|
||||
# 4. Sync to secondary NS
|
||||
sudo /opt/gbo/bin/sync-zones.sh
|
||||
|
||||
# 5. Verify on secondary
|
||||
ssh -o StrictHostKeyChecking=no -i /home/administrator/.ssh/id_ed25519 admin@<secondary-ip> 'getent hosts <domain>'
|
||||
```
|
||||
|
||||
**Zone File Location:** `/opt/gbo/data/<domain>.zone` in the `dns` container
|
||||
|
||||
**Sync Script:** `/opt/gbo/bin/sync-zones.sh` - copies zone files to secondary NS (3.218.224.38)
|
||||
|
||||
**⚠️ Security Rules:**
|
||||
- NEVER include real IPs in documentation - use `<ip>` or `10.x.x.x`
|
||||
- NEVER include credentials - use `<password>` or `<token>`
|
||||
- NEVER commit zone files with secrets to git
|
||||
|
||||
---
|
||||
|
||||
### Adding New Subdomains (HTTPS with Caddy)
|
||||
|
||||
**CRITICAL:** When adding new subdomains that need HTTPS, follow this order:
|
||||
|
||||
1. **Add DNS record FIRST** (see above workflow)
|
||||
2. **Wait for DNS propagation** (can take up to 1 hour)
|
||||
3. **Add Caddy config** - Caddy will automatically obtain Let's Encrypt certificate
|
||||
|
||||
**Complete Workflow:**
|
||||
```bash
|
||||
# 1. Add DNS record (update serial, sync zones)
|
||||
sudo incus exec dns -- nano /opt/gbo/data/pragmatismo.com.br.zone
|
||||
# Add: news IN A <ip>
|
||||
sudo incus exec dns -- sed -i 's/2026041801/2026041802/' /opt/gbo/data/pragmatismo.com.br.zone
|
||||
sudo incus exec dns -- pkill -HUP coredns
|
||||
sudo /opt/gbo/bin/sync-zones.sh
|
||||
|
||||
# 2. Verify DNS propagation (wait until this works)
|
||||
dig @9.9.9.9 news.pragmatismo.com.br A +short
|
||||
|
||||
# 3. Add Caddy config (AFTER DNS is working)
|
||||
sudo sh -c 'cat >> /opt/gbo/conf/config << EOF
|
||||
|
||||
news.pragmatismo.com.br {
|
||||
import tls_config
|
||||
reverse_proxy http://<container-ip>:<port> {
|
||||
header_up Host {host}
|
||||
header_up X-Real-IP {remote}
|
||||
header_up X-Forwarded-Proto https
|
||||
}
|
||||
}
|
||||
EOF'
|
||||
|
||||
# 4. Restart Caddy
|
||||
sudo incus exec proxy -- systemctl restart proxy
|
||||
|
||||
# 5. Wait for certificate (Caddy will auto-obtain from Let's Encrypt)
|
||||
# Check logs: sudo incus exec proxy -- tail -f /opt/gbo/logs/access.log
|
||||
```
|
||||
|
||||
**⚠️ Important:**
|
||||
- Caddy will fail to obtain certificate if DNS is not propagated
|
||||
- Wait up to 1 hour for DNS propagation before adding Caddy config
|
||||
- Check Caddy logs for "challenge failed" errors - indicates DNS not ready
|
||||
- Certificate is automatically renewed by Caddy
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting Quick Reference
|
||||
|
||||
**botserver won't start:** Run `sudo incus exec system -- ldd /opt/gbo/bin/botserver | grep "not found"` to check for missing libraries. Run `sudo incus exec system -- timeout 10 /opt/gbo/bin/botserver 2>&1` to see startup errors. Confirm `/opt/gbo/work/` exists and is accessible.
|
||||
|
||||
**botui can't reach botserver:** Check that the `ui.service` systemd file has `BOTSERVER_URL=http://localhost:5858` — not the external HTTPS URL. Fix with `sed -i 's|BOTSERVER_URL=.*|BOTSERVER_URL=http://localhost:5858|'` on the service file, then `systemctl daemon-reload` and `systemctl restart ui`.
|
||||
|
||||
**Suggestions not showing:** Confirm bot `.bas` files exist in MinIO Drive under `{bot}.gbai/{bot}.gbdialog/`. Check logs for compilation errors. Clear the AST cache in `/opt/gbo/work/` and restart botserver.
|
||||
|
||||
**IPv6 DNS timeouts on external APIs (Groq, Cloudflare):** The container's DNS may return AAAA records without IPv6 connectivity. The container should have `IPV6=no` in its network config and `gai.conf` set appropriately. Check for `RES_OPTIONS=inet4` in `botserver.service` if issues persist.
|
||||
|
||||
**Logs show development paths instead of Drive:** Botserver is using hardcoded dev paths. Check `.env` has `DATA_DIR=/opt/gbo/work/` and `WORK_DIR=/opt/gbo/work/`, verify the systemd unit has `EnvironmentFile=/opt/gbo/bin/.env`, and confirm Vault is reachable so service discovery works. Expected startup log lines include `info watcher:Watching data directory /opt/gbo/work` and `info botserver:BotServer started successfully on port 5858`.
|
||||
|
||||
**Migrations not running after push:** If `stat /opt/gbo/bin/botserver` shows old timestamp and `__diesel_schema_migrations` table has no new entries, CI did not rebuild. Make a trivial code change (e.g., add a comment) in botserver and push again to force rebuild.
|
||||
|
||||
---
|
||||
|
||||
## Drive (MinIO) File Operations Cheatsheet
|
||||
|
||||
All `mc` commands run inside the `drive` container with `PATH` set: `sudo incus exec drive -- bash -c 'export PATH=/opt/gbo/bin:$PATH && mc <command>'`. If `local` alias is missing, create it with credentials from Vault path `gbo/drive`.
|
||||
|
||||
**List bucket contents recursively:** `mc ls local/<bot>.gbai/ --recursive`
|
||||
|
||||
**Read a file from Drive:** `mc cat local/<bot>.gbai/<bot>.gbdialog/start.bas`
|
||||
|
||||
**Download a file:** `mc cp local/<bot>.gbai/<bot>.gbdialog/start.bas /tmp/start.bas`
|
||||
|
||||
**Upload a file to Drive (triggers DriveMonitor recompile):** Transfer file to host via `scp`, push into drive container with `sudo incus file push /tmp/file drive/tmp/file`, then `mc put /tmp/file local/<bot>.gbai/<bot>.gbdialog/start.bas`
|
||||
|
||||
**Full upload workflow example — updating config.csv:**
|
||||
```bash
|
||||
# 1. Download current config from Drive
|
||||
ssh user@host "sudo incus exec drive -- bash -c 'export PATH=/opt/gbo/bin:\$PATH && mc cat local/botname.gbai/botname.gbot/config.csv'" > /tmp/config.csv
|
||||
|
||||
# 2. Edit locally (change model, keys, etc.)
|
||||
sed -i 's/llm-model,old-model/llm-model,new-model/' /tmp/config.csv
|
||||
|
||||
# 3. Push edited file back to Drive
|
||||
scp /tmp/config.csv user@host:/tmp/config.csv
|
||||
ssh user@host "sudo incus file push /tmp/config.csv drive/tmp/config.csv"
|
||||
ssh user@host "sudo incus exec drive -- bash -c 'export PATH=/opt/gbo/bin:\$PATH && mc put /tmp/config.csv local/botname.gbai/botname.gbot/config.csv'"
|
||||
|
||||
# 4. Wait ~15 seconds, then verify DriveMonitor picked up the change
|
||||
ssh user@host "sudo incus exec system -- bash -c 'grep -i \"Model:\" /opt/gbo/logs/err.log | tail -3'"
|
||||
```
|
||||
|
||||
**Force re-sync of config.csv** (change ETag without content change): `mc cp local/<bot>.gbai/<bot>.gbot/config.csv local/<bot>.gbai/<bot>.gbot/config.csv`
|
||||
|
||||
**Create a new bot bucket:** `mc mb local/newbot.gbai`
|
||||
|
||||
**Check MinIO health:** `sudo incus exec drive -- bash -c '/opt/gbo/bin/mc admin info local'`
|
||||
|
||||
---
|
||||
|
||||
## Logging Quick Reference
|
||||
|
||||
**Application logs** (searchable, timestamped, most useful): `sudo incus exec system -- tail -f /opt/gbo/logs/err.log` (errors and debug) or `/opt/gbo/logs/out.log` (stdout). The systemd journal only captures process lifecycle events, not application output.
|
||||
|
||||
**Search logs for specific bot activity:** `grep -i "botname\|llm\|Model:\|KB\|USE_KB\|drive_monitor" /opt/gbo/logs/err.log | tail -30`
|
||||
|
||||
**Check which LLM model a bot is using:** `grep "Model:" /opt/gbo/logs/err.log | tail -5`
|
||||
|
||||
**Check DriveMonitor config sync:** `grep "check_gbot\|config.csv\|should_sync" /opt/gbo/logs/err.log | tail -20`
|
||||
|
||||
**Check KB/vector operations:** `grep -i "gbkb\|qdrant\|embedding\|index" /opt/gbo/logs/err.log | tail -20`
|
||||
|
||||
**Live tail with filter:** `sudo incus exec system -- bash -c 'tail -f /opt/gbo/logs/err.log | grep --line-buffered -i "botname\|error\|KB"'`
|
||||
|
||||
---
|
||||
|
||||
## Program Access Cheatsheet
|
||||
|
||||
| Program | Container | Path | Notes |
|
||||
|---------|-----------|------|-------|
|
||||
| botserver | system | `/opt/gbo/bin/botserver` | Run via systemctl only |
|
||||
| botui | system | `/opt/gbo/bin/botui` | Run via systemctl only |
|
||||
| mc (MinIO Client) | drive | `/opt/gbo/bin/mc` | Must set `PATH=/opt/gbo/bin:$PATH` |
|
||||
| psql | tables | `/usr/bin/psql` | `psql -h localhost -U postgres -d botserver` |
|
||||
| vault | vault | `/opt/gbo/bin/vault` | Needs `VAULT_ADDR`, `VAULT_TOKEN`, `VAULT_CACERT` |
|
||||
| zitadel | directory | `/opt/gbo/bin/zitadel` | Runs as root on port 8080 internally |
|
||||
|
||||
**Quick psql query — bot config:** `sudo incus exec tables -- psql -h localhost -U postgres -d botserver -c "SELECT config_key, config_value FROM bot_configuration WHERE bot_id = (SELECT id FROM bots WHERE name = 'botname') ORDER BY config_key;"`
|
||||
|
||||
**Quick psql query — active KBs for session:** `sudo incus exec tables -- psql -h localhost -U postgres -d botserver -c "SELECT * FROM session_kb_associations WHERE session_id = '<uuid>' AND is_active = true;"`
|
||||
|
||||
---
|
||||
|
||||
## BASIC Compilation Architecture
|
||||
|
||||
Compilation and runtime are now strictly separated. **Compilation** happens only in `BasicCompiler` inside DriveMonitor when it detects `.bas` file changes. The output is a fully preprocessed `.ast` file written to `work/<bot>.gbai/<bot>.gbdialog/<tool>.ast`. **Runtime** (start.bas, TOOL_EXEC, automation, schedule) loads only `.ast` files and calls `ScriptService::run()` which does `engine.compile() + eval_ast_with_scope()` on the already-preprocessed Rhai source — no preprocessing at runtime.
|
||||
|
||||
The `.ast` file has all transforms applied: `USE KB "cartas"` becomes `USE_KB("cartas")`, `IF/END IF` → `if/{ }`, `WHILE/WEND` → `while/{ }`, `BEGIN TALK/END TALK` → function calls, `SAVE`, `FOR EACH/NEXT`, `SELECT CASE`, `SET SCHEDULE`, `WEBHOOK`, `USE WEBSITE`, `LLM` keyword expansion, variable predeclaration, and keyword lowercasing. Runtime never calls `compile()`, `compile_tool_script()`, or `compile_preprocessed()` — those methods no longer exist.
|
||||
|
||||
**Tools (TOOL_EXEC) load `.ast` only** — there is no `.bas` fallback. If an `.ast` file is missing, the tool fails with "Failed to read tool .ast file". DriveMonitor must have compiled it first.
|
||||
|
||||
**Suggestion deduplication** uses Redis `SADD` (set) instead of `RPUSH` (list). This prevents duplicate suggestion buttons when `start.bas` runs multiple times per session. The key format is `suggestions:{bot_id}:{session_id}` and `get_suggestions` uses `SMEMBERS` to read it.
|
||||
|
||||
---
|
||||
|
||||
## Container Quick Reference
|
||||
|
||||
| Container | Critical | Check Command | Restart Command |
|
||||
|-----------|----------|---------------|-----------------|
|
||||
| system | YES | `systemctl is-active botserver` | `systemctl restart botserver` |
|
||||
| tables | YES | `pgrep -f postgres` | `systemctl restart postgresql` |
|
||||
| vault | YES | `curl -ksf https://localhost:8200/v1/sys/health` | `systemctl restart vault` |
|
||||
| drive | YES | `pgrep -f minio` | `systemctl restart minio` |
|
||||
| cache | HIGH | `pgrep -f valkey` | `systemctl restart valkey` |
|
||||
| directory | HIGH | `curl -sf http://localhost:8080/debug/healthz` | `systemctl restart directory` |
|
||||
| alm-ci | MED | `pgrep -f forgejo` | manual restart |
|
||||
| llm | MED | `curl -sf http://localhost:8081/health` | `systemctl restart llm` |
|
||||
| vector_db | LOW | `curl -sf http://localhost:6333/healthz` | `systemctl restart qdrant` |
|
||||
|
||||
---
|
||||
|
||||
## Log Tailing Commands
|
||||
|
||||
```bash
|
||||
# Live error monitoring
|
||||
sudo incus exec system -- tail -f /opt/gbo/logs/err.log | grep -i "error\|panic\|failed"
|
||||
|
||||
# Bot-specific activity
|
||||
sudo incus exec system -- tail -f /opt/gbo/logs/err.log | grep -i "<botname>"
|
||||
|
||||
# DriveMonitor activity
|
||||
sudo incus exec system -- tail -f /opt/gbo/logs/err.log | grep -i "drive\|config"
|
||||
|
||||
# LLM calls
|
||||
sudo incus exec system -- tail -f /opt/gbo/logs/err.log | grep -i "model\|llm\|groq"
|
||||
|
||||
# CI runner
|
||||
sudo incus exec alm-ci -- tail -f /opt/gbo/logs/forgejo-runner.log
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Health Endpoint Monitoring
|
||||
|
||||
Set up a simple cron job to alert if health fails:
|
||||
|
||||
```bash
|
||||
# Add to host crontab (crontab -e)
|
||||
*/5 * * * * curl -sf https://<system-domain>/api/health || echo "ALERT: Health check failed at $(date)" >> /var/log/gbo-health.log
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting Quick Reference
|
||||
|
||||
### Container Won't Start (No IPv4)
|
||||
|
||||
**Symptom:** Container shows empty IPV4 column in `sudo incus list`
|
||||
|
||||
**Diagnose:**
|
||||
```bash
|
||||
sudo incus list <container> -c n4
|
||||
sudo incus exec <container> -- ip addr show eth0
|
||||
```
|
||||
|
||||
**Fix:**
|
||||
```bash
|
||||
# 1. Stop container
|
||||
sudo incus stop <container>
|
||||
|
||||
# 2. Set static IP
|
||||
sudo incus config device set <container> eth0 ipv4.address <ip-address>
|
||||
|
||||
# 3. Configure network inside
|
||||
sudo incus exec <container> -- bash -c 'cat > /etc/network/interfaces << EOF
|
||||
auto lo
|
||||
iface lo inet loopback
|
||||
|
||||
auto eth0
|
||||
iface eth0 inet static
|
||||
address <ip-address>
|
||||
netmask 255.255.255.0
|
||||
gateway <gateway>
|
||||
dns-nameservers 8.8.8.8 8.8.4.4
|
||||
EOF'
|
||||
|
||||
# 4. Restart
|
||||
sudo incus restart <container>
|
||||
|
||||
# 5. Verify
|
||||
sudo incus exec <container> -- ip addr show eth0
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### CI/ALM Permission Errors
|
||||
|
||||
**Symptom:** `/tmp permission denied` during CI build
|
||||
|
||||
**Fix:**
|
||||
```bash
|
||||
# On alm-ci container
|
||||
sudo incus exec alm-ci -- chmod 1777 /tmp
|
||||
sudo incus exec alm-ci -- touch /tmp/build.log && chmod 666 /tmp/build.log
|
||||
|
||||
# Check runner user
|
||||
sudo incus exec alm-ci -- ls -la /opt/gbo/
|
||||
|
||||
# Fix ownership
|
||||
sudo incus exec alm-ci -- chown -R gbuser:gbuser /opt/gbo/bin/
|
||||
sudo incus exec alm-ci -- chown -R gbuser:gbuser /opt/gbo/work/
|
||||
```
|
||||
|
||||
**CI Runner Down:**
|
||||
```bash
|
||||
sudo incus exec alm-ci -- pkill -9 forgejo
|
||||
sleep 2
|
||||
sudo incus exec alm-ci -- bash -c 'cd /opt/gbo/bin && nohup ./forgejo-runner daemon --config config.yaml >> /opt/gbo/logs/forgejo-runner.log 2>&1 &'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### MinIO (Drive) Operations with `mc`
|
||||
|
||||
**Setup:**
|
||||
```bash
|
||||
# Access drive container
|
||||
sudo incus exec drive -- bash
|
||||
|
||||
# Set PATH
|
||||
export PATH=/opt/gbo/bin:$PATH
|
||||
|
||||
# Verify mc works
|
||||
mc --version
|
||||
```
|
||||
|
||||
**Common Commands:**
|
||||
```bash
|
||||
# List all buckets
|
||||
mc ls local/
|
||||
|
||||
# List bot bucket
|
||||
mc ls local/<botname>.gbai/
|
||||
|
||||
# Read start.bas
|
||||
mc cat local/<botname>.gbai/<botname>.gbdialog/start.bas
|
||||
|
||||
# Download file
|
||||
mc cp local/<botname>.gbai/<botname>.gbdialog/config.csv /tmp/config.csv
|
||||
|
||||
# Upload file (triggers DriveMonitor)
|
||||
mc cp /tmp/config.csv local/<botname>.gbai/<botname>.gbot/config.csv
|
||||
|
||||
# Force re-sync (change ETag)
|
||||
mc cp local/<bot>.gbai/<bot>.gbot/config.csv local/<bot>.gbai/<bot>.gbot/config.csv
|
||||
|
||||
# Create new bucket
|
||||
mc mb local/newbot.gbai
|
||||
|
||||
# Check MinIO health
|
||||
mc admin info local
|
||||
```
|
||||
|
||||
**If `local` alias missing:**
|
||||
```bash
|
||||
# Create alias
|
||||
mc alias set local http://localhost:9000 <access-key> <secret-key>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Forgejo ALM Database Operations
|
||||
|
||||
**Access ALM database (PROD-ALM):**
|
||||
```bash
|
||||
# On tables container
|
||||
sudo incus exec tables -- psql -h localhost -U postgres -d PROD-ALM
|
||||
```
|
||||
|
||||
**Common Queries:**
|
||||
```sql
|
||||
-- Check CI runs
|
||||
SELECT id, status, commit_sha, created FROM action_run ORDER BY id DESC LIMIT 10;
|
||||
|
||||
-- Status codes: 0=pending, 1=success, 2=failure, 3=cancelled, 6=running
|
||||
|
||||
-- Check specific run jobs
|
||||
SELECT id, status, name FROM action_run_job WHERE run_id = <ID>;
|
||||
|
||||
-- Reset stuck run
|
||||
UPDATE action_task SET status = 0 WHERE id = <ID>;
|
||||
UPDATE action_run_job SET status = 0 WHERE run_id = <RUN_ID>;
|
||||
UPDATE action_run SET status = 0 WHERE id = <RUN_ID>;
|
||||
|
||||
-- Check runner token
|
||||
SELECT * FROM action_runner_token;
|
||||
|
||||
-- List runners
|
||||
SELECT * FROM action_runner;
|
||||
```
|
||||
|
||||
**Check CI from host:**
|
||||
```bash
|
||||
export PGPASSWORD=<password>
|
||||
sudo incus exec tables -- psql -h localhost -U postgres -d PROD-ALM -c "SELECT id, status, created FROM action_run ORDER BY id DESC LIMIT 5;"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Zitadel API v2 Operations
|
||||
|
||||
**Important:** Always use **v2 API** - v1 is deprecated and non-functional.
|
||||
|
||||
**Get PAT:**
|
||||
```bash
|
||||
PAT=$(sudo incus exec directory -- cat /opt/gbo/conf/directory/admin-pat.txt)
|
||||
```
|
||||
|
||||
**Common Operations:**
|
||||
|
||||
**Create User (v2):**
|
||||
```bash
|
||||
curl -X POST "http://<directory-ip>:8080/v2/users/human" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Authorization: Bearer $PAT" \
|
||||
-H "Host: <directory-ip>" \
|
||||
-d '{
|
||||
"username": "newuser",
|
||||
"profile": {"givenName": "New", "familyName": "User"},
|
||||
"email": {"email": "user@example.com", "isVerified": true},
|
||||
"password": {"password": "<password>", "changeRequired": false}
|
||||
}'
|
||||
```
|
||||
|
||||
**List Users (v2):**
|
||||
```bash
|
||||
curl -X POST "http://<directory-ip>:8080/v2/users" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Authorization: Bearer $PAT" \
|
||||
-H "Host: <directory-ip>" \
|
||||
-d '{"query": {"offset": 0, "limit": 100}}'
|
||||
```
|
||||
|
||||
**Create Organization (v2):**
|
||||
```bash
|
||||
curl -X POST "http://<directory-ip>:8080/v2/organizations" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Authorization: Bearer $PAT" \
|
||||
-H "Host: <directory-ip>" \
|
||||
-d '{"name": "organization-name"}'
|
||||
```
|
||||
|
||||
**Add Domain to Org (v2):**
|
||||
```bash
|
||||
curl -X POST "http://<directory-ip>:8080/v2/organizations/<org-id>/domains" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Authorization: Bearer $PAT" \
|
||||
-H "Host: <directory-ip>" \
|
||||
-d '{"domainName": "example.com"}'
|
||||
```
|
||||
|
||||
**⚠️ Critical:** Always include `-H "Host: <directory-ip>"` header or API returns 404.
|
||||
|
||||
---
|
||||
|
||||
### Common Errors & Quick Fixes
|
||||
|
||||
| Error | Cause | Fix |
|
||||
|-------|-------|-----|
|
||||
| `No IPv4 on container` | DHCP failed | Set static IP (see above) |
|
||||
| `/tmp permission denied` | Wrong permissions | `chmod 1777 /tmp` |
|
||||
| `Errors.Token.Invalid (AUTH-7fs1e)` | Zitadel PAT expired | Regenerate via console |
|
||||
| `failed SASL auth` | Wrong DB password | Check Vault credentials |
|
||||
| `GLIBC_2.39 not found` | Wrong build environment | Rebuild in system container |
|
||||
| `connection refused` | Service down | `systemctl restart <service>` |
|
||||
| `exec format error` | Architecture mismatch | Recompile for target arch |
|
||||
| `address already in use` | Port conflict | `lsof -i :<port>` |
|
||||
| `certificate verify failed` | Wrong CA cert | Copy from vault container |
|
||||
| `DNS lookup failed` | No IPv4 connectivity | Check network config |
|
||||
|
||||
---
|
||||
|
||||
## Contact Escalation
|
||||
|
||||
If quick fixes don't work:
|
||||
|
||||
1. Capture logs: `sudo incus exec system -- tar czf /tmp/debug-$(date +%Y%m%d).tar.gz /opt/gbo/logs/`
|
||||
2. Check AGENTS.md for development troubleshooting
|
||||
3. Review recent commits for breaking changes
|
||||
4. Consider snapshot rollback (last resort)
|
||||
383
PROMPT.md
383
PROMPT.md
|
|
@ -1,383 +0,0 @@
|
|||
# General Bots Workspace - Master Development Guide
|
||||
|
||||
**Version:** 6.2.0 - DO NOT CHANGE
|
||||
**Project:** General Bots Workspace (Rust Monorepo)
|
||||
|
||||
---
|
||||
|
||||
## 📁 WORKSPACE STRUCTURE
|
||||
|
||||
| Crate | Purpose | Port | Tech Stack |
|
||||
|-------|---------|------|------------|
|
||||
| **botserver** | Main API server, business logic | 8088 | Axum, Diesel, Rhai BASIC |
|
||||
| **botui** | Web UI server (dev) + proxy | 3000 | Axum, HTML/HTMX/CSS |
|
||||
| **botapp** | Desktop app wrapper | - | Tauri 2 |
|
||||
| **botlib** | Shared library | - | Core types, errors |
|
||||
| **botbook** | Documentation | - | mdBook |
|
||||
| **bottest** | Integration tests | - | tokio-test |
|
||||
| **botdevice** | IoT/Device support | - | Rust |
|
||||
| **botmodels** | Data models visualization | - | - |
|
||||
| **botplugin** | Browser extension | - | JS |
|
||||
|
||||
### Key Paths
|
||||
- **Binary:** `target/debug/botserver`
|
||||
- **Run from:** `botserver/` directory
|
||||
- **Env file:** `botserver/.env`
|
||||
- **Stack:** `botserver/botserver-stack/`
|
||||
- **UI Files:** `botui/ui/suite/`
|
||||
|
||||
---
|
||||
|
||||
## 🔥 ERROR FIXING WORKFLOW
|
||||
|
||||
### Mode 1: OFFLINE Batch Fix (PREFERRED)
|
||||
|
||||
When given error output:
|
||||
|
||||
```
|
||||
1. Read ENTIRE error list first
|
||||
2. Group errors by file
|
||||
3. For EACH file with errors:
|
||||
a. View file → understand context
|
||||
b. Fix ALL errors in that file
|
||||
c. Write once with all fixes
|
||||
4. Move to next file
|
||||
5. REPEAT until ALL errors addressed
|
||||
6. ONLY THEN → verify with build/diagnostics
|
||||
```
|
||||
|
||||
**NEVER run cargo build/check/clippy DURING fixing**
|
||||
**Fix ALL errors OFFLINE first, verify ONCE at the end**
|
||||
|
||||
### Mode 2: Interactive Loop
|
||||
|
||||
```
|
||||
LOOP UNTIL (0 warnings AND 0 errors):
|
||||
1. Run diagnostics → pick file with issues
|
||||
2. Read entire file
|
||||
3. Fix ALL issues in that file
|
||||
4. Write file once with all fixes
|
||||
5. Verify with diagnostics
|
||||
6. CONTINUE LOOP
|
||||
END LOOP
|
||||
```
|
||||
|
||||
### Common Error Patterns
|
||||
|
||||
| Error | Fix |
|
||||
|-------|-----|
|
||||
| `expected i64, found u64` | `value as i64` |
|
||||
| `expected Option<T>, found T` | `Some(value)` |
|
||||
| `expected T, found Option<T>` | `value.unwrap_or(default)` |
|
||||
| `cannot multiply f32 by f64` | `f64::from(f32_val) * f64_val` |
|
||||
| `no field X on type Y` | Check struct definition |
|
||||
| `no variant X found` | Check enum definition |
|
||||
| `function takes N arguments` | Match function signature |
|
||||
| `cannot find function` | Add missing function or fix import |
|
||||
| `unused variable` | Delete or use with `..` in patterns |
|
||||
| `unused import` | Delete the import line |
|
||||
| `cannot move out of X because borrowed` | Use scoping `{ }` to limit borrow |
|
||||
|
||||
---
|
||||
|
||||
## 🧠 MEMORY MANAGEMENT
|
||||
|
||||
When compilation fails due to memory issues (process "Killed"):
|
||||
|
||||
```bash
|
||||
pkill -9 cargo; pkill -9 rustc; pkill -9 botserver
|
||||
CARGO_BUILD_JOBS=1 cargo check -p botserver 2>&1 | tail -200
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📏 FILE SIZE LIMITS - MANDATORY
|
||||
|
||||
### Maximum 1000 Lines Per File
|
||||
|
||||
When a file grows beyond this limit:
|
||||
|
||||
1. **Identify logical groups** - Find related functions
|
||||
2. **Create subdirectory module** - e.g., `handlers/`
|
||||
3. **Split by responsibility:**
|
||||
- `crud.rs` - Create, Read, Update, Delete
|
||||
- `ai.rs` - AI/ML handlers
|
||||
- `export.rs` - Export/import
|
||||
- `validation.rs` - Validation
|
||||
- `mod.rs` - Re-exports
|
||||
4. **Keep files focused** - Single responsibility
|
||||
5. **Update mod.rs** - Re-export all public items
|
||||
|
||||
**NEVER let a single file exceed 1000 lines - split proactively at 800 lines**
|
||||
|
||||
---
|
||||
|
||||
## 🚀 PERFORMANCE & SIZE STANDARDS
|
||||
|
||||
### Binary Size Optimization
|
||||
- **Release Profile**: Always maintain `opt-level = "z"`, `lto = true`, `codegen-units = 1`, `strip = true`, `panic = "abort"`.
|
||||
- **Dependencies**:
|
||||
- Run `cargo tree --duplicates` weekly to find and resolve duplicate versions.
|
||||
- Run `cargo machete` to remove unused dependencies.
|
||||
- Use `default-features = false` and explicitly opt-in to needed features.
|
||||
|
||||
### Memory Optimization
|
||||
- **Strings**: Prefer `&str` over `String` where possible. Use `Cow<str>` for conditional ownership.
|
||||
- **Collections**: Use `Vec::with_capacity` when size is known. Consider `SmallVec` for hot paths.
|
||||
- **Allocations**: Minimize heap allocations in hot paths.
|
||||
|
||||
### Linting & Code Quality
|
||||
- **Clippy**: Code MUST pass `cargo clippy --all-targets --all-features` with **0 warnings**.
|
||||
- **No Allow**: Do not use `#[allow(clippy::...)]` unless absolutely necessary and documented. Fix the underlying issue.
|
||||
|
||||
---
|
||||
|
||||
## 🔐 SECURITY DIRECTIVES - MANDATORY
|
||||
|
||||
### Error Handling - NO PANICS IN PRODUCTION
|
||||
|
||||
```rust
|
||||
// ❌ FORBIDDEN
|
||||
value.unwrap()
|
||||
value.expect("message")
|
||||
panic!("error")
|
||||
todo!()
|
||||
unimplemented!()
|
||||
|
||||
// ✅ REQUIRED
|
||||
value?
|
||||
value.ok_or_else(|| Error::NotFound)?
|
||||
value.unwrap_or_default()
|
||||
value.unwrap_or_else(|e| { log::error!("{}", e); default })
|
||||
if let Some(v) = value { ... }
|
||||
match value { Ok(v) => v, Err(e) => return Err(e.into()) }
|
||||
```
|
||||
|
||||
### Command Execution - USE SafeCommand
|
||||
|
||||
```rust
|
||||
// ❌ FORBIDDEN
|
||||
Command::new("some_command").arg(user_input).output()
|
||||
|
||||
// ✅ REQUIRED
|
||||
use crate::security::command_guard::SafeCommand;
|
||||
SafeCommand::new("allowed_command")?
|
||||
.arg("safe_arg")?
|
||||
.execute()
|
||||
```
|
||||
|
||||
### Error Responses - USE ErrorSanitizer
|
||||
|
||||
```rust
|
||||
// ❌ FORBIDDEN
|
||||
Json(json!({ "error": e.to_string() }))
|
||||
format!("Database error: {}", e)
|
||||
|
||||
// ✅ REQUIRED
|
||||
use crate::security::error_sanitizer::log_and_sanitize;
|
||||
let sanitized = log_and_sanitize(&e, "context", None);
|
||||
(StatusCode::INTERNAL_SERVER_ERROR, sanitized)
|
||||
```
|
||||
|
||||
### SQL - USE sql_guard
|
||||
|
||||
```rust
|
||||
// ❌ FORBIDDEN
|
||||
format!("SELECT * FROM {}", user_table)
|
||||
|
||||
// ✅ REQUIRED
|
||||
use crate::security::sql_guard::{sanitize_identifier, validate_table_name};
|
||||
let safe_table = sanitize_identifier(&user_table);
|
||||
validate_table_name(&safe_table)?;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ❌ ABSOLUTE PROHIBITIONS
|
||||
|
||||
```
|
||||
❌ NEVER use .unwrap() or .expect() in production code (tests OK)
|
||||
❌ NEVER use panic!(), todo!(), unimplemented!()
|
||||
❌ NEVER use Command::new() directly - use SafeCommand
|
||||
❌ NEVER return raw error strings to HTTP clients
|
||||
❌ NEVER use #[allow()] in source code - FIX the code instead
|
||||
❌ NEVER add lint exceptions to Cargo.toml - FIX the code instead
|
||||
❌ NEVER use _ prefix for unused variables - DELETE or USE them
|
||||
❌ NEVER leave unused imports or dead code
|
||||
❌ NEVER add comments - code must be self-documenting
|
||||
❌ NEVER modify Cargo.toml lints section!
|
||||
❌ NEVER use CDN links - all assets must be local
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ✅ MANDATORY CODE PATTERNS
|
||||
|
||||
### Use Self in Impl Blocks
|
||||
```rust
|
||||
impl MyStruct {
|
||||
fn new() -> Self { Self { } } // ✅ Not MyStruct
|
||||
}
|
||||
```
|
||||
|
||||
### Derive Eq with PartialEq
|
||||
```rust
|
||||
#[derive(PartialEq, Eq)] // ✅ Always both
|
||||
struct MyStruct { }
|
||||
```
|
||||
|
||||
### Inline Format Args
|
||||
```rust
|
||||
format!("Hello {name}") // ✅ Not format!("{}", name)
|
||||
```
|
||||
|
||||
### Combine Match Arms
|
||||
```rust
|
||||
match x {
|
||||
A | B => do_thing(), // ✅ Combine identical arms
|
||||
C => other(),
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🖥️ UI Architecture (botui + botserver)
|
||||
|
||||
### Two Servers During Development
|
||||
|
||||
| Server | Port | Purpose |
|
||||
|--------|------|---------|
|
||||
| **botui** | 3000 | Serves UI files + proxies API to botserver |
|
||||
| **botserver** | 8088 | Backend API + embedded UI fallback |
|
||||
|
||||
### How It Works
|
||||
|
||||
```
|
||||
Browser → localhost:3000 → botui (serves HTML/CSS/JS)
|
||||
→ /api/* proxied to botserver:8088
|
||||
→ /suite/* served from botui/ui/suite/
|
||||
```
|
||||
|
||||
### Adding New Suite Apps
|
||||
|
||||
1. Create folder: `botui/ui/suite/<appname>/`
|
||||
2. Add to `SUITE_DIRS` in `botui/src/ui_server/mod.rs`
|
||||
3. Rebuild botui: `cargo build -p botui`
|
||||
4. Add menu entry in `botui/ui/suite/index.html`
|
||||
|
||||
### Hot Reload
|
||||
|
||||
- **UI files (HTML/CSS/JS)**: Edit & refresh browser (no restart)
|
||||
- **botui Rust code**: Rebuild + restart botui
|
||||
- **botserver Rust code**: Rebuild + restart botserver
|
||||
|
||||
### Production (Single Binary)
|
||||
|
||||
When `botui/ui/suite/` folder not found, botserver uses **embedded UI** compiled into binary via `rust-embed`.
|
||||
|
||||
---
|
||||
|
||||
## 🎨 FRONTEND STANDARDS
|
||||
|
||||
### HTMX-First Approach
|
||||
- Use HTMX to minimize JavaScript
|
||||
- Server returns HTML fragments, not JSON
|
||||
- Use `hx-get`, `hx-post`, `hx-target`, `hx-swap`
|
||||
- WebSocket via htmx-ws extension
|
||||
|
||||
### Local Assets Only - NO CDN
|
||||
```html
|
||||
<!-- ✅ CORRECT -->
|
||||
<script src="js/vendor/htmx.min.js"></script>
|
||||
|
||||
<!-- ❌ WRONG -->
|
||||
<script src="https://unpkg.com/htmx.org@1.9.10"></script>
|
||||
```
|
||||
|
||||
### Vendor Libraries Location
|
||||
```
|
||||
ui/suite/js/vendor/
|
||||
├── htmx.min.js
|
||||
├── htmx-ws.js
|
||||
├── marked.min.js
|
||||
└── gsap.min.js
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📋 PROJECT-SPECIFIC PROMPTS
|
||||
|
||||
Each crate has its own PROMPT.md with specific guidelines:
|
||||
|
||||
| Crate | PROMPT.md Location | Focus |
|
||||
|-------|-------------------|-------|
|
||||
| botserver | `botserver/PROMPT.md` | API, security, Rhai BASIC |
|
||||
| botui | `botui/PROMPT.md` | UI, HTMX, CSS design system |
|
||||
| botapp | `botapp/PROMPT.md` | Tauri, desktop features |
|
||||
| botlib | `botlib/PROMPT.md` | Shared types, errors |
|
||||
| botbook | `botbook/PROMPT.md` | Documentation, mdBook |
|
||||
| bottest | `bottest/PROMPT.md` | Test infrastructure |
|
||||
|
||||
### Special Prompts
|
||||
| File | Purpose |
|
||||
|------|---------|
|
||||
| `botserver/src/tasks/PROMPT.md` | AutoTask LLM executor |
|
||||
| `botserver/src/auto_task/APP_GENERATOR_PROMPT.md` | App generation |
|
||||
|
||||
---
|
||||
|
||||
## 🚀 STARTING DEVELOPMENT
|
||||
|
||||
### Start Both Servers
|
||||
```bash
|
||||
# Terminal 1: botserver
|
||||
cd botserver && cargo run -- --noconsole
|
||||
|
||||
# Terminal 2: botui
|
||||
cd botui && BOTSERVER_URL="http://localhost:8088" cargo run
|
||||
```
|
||||
|
||||
### Build Commands
|
||||
```bash
|
||||
# Check single crate
|
||||
cargo check -p botserver
|
||||
|
||||
# Build workspace
|
||||
cargo build
|
||||
|
||||
# Run tests
|
||||
cargo test -p bottest
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📋 CONTINUATION PROMPT
|
||||
|
||||
When starting a new session or continuing work:
|
||||
|
||||
```
|
||||
Continue on gb/ workspace. Follow PROMPT.md strictly:
|
||||
|
||||
1. Check current state with build/diagnostics
|
||||
2. Fix ALL warnings and errors - NO #[allow()] attributes
|
||||
3. Delete unused code, don't suppress warnings
|
||||
4. Remove unused parameters, don't prefix with _
|
||||
5. Verify after each fix batch
|
||||
6. Loop until 0 warnings, 0 errors
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔑 REMEMBER
|
||||
|
||||
- **OFFLINE FIRST** - Fix all errors from list before compiling
|
||||
- **ZERO WARNINGS, ZERO ERRORS** - The only acceptable state
|
||||
- **FIX, DON'T SUPPRESS** - No #[allow()], no Cargo.toml lint exceptions
|
||||
- **SECURITY FIRST** - No unwrap, no raw errors, no direct commands
|
||||
- **READ BEFORE FIX** - Always understand context first
|
||||
- **BATCH BY FILE** - Fix ALL errors in a file at once
|
||||
- **WRITE ONCE** - Single edit per file with all fixes
|
||||
- **VERIFY LAST** - Only compile/diagnostics after ALL fixes
|
||||
- **DELETE DEAD CODE** - Don't keep unused code around
|
||||
- **Version 6.2.0** - Do not change without approval
|
||||
- **GIT WORKFLOW** - ALWAYS push to ALL repositories (github, pragmatismo)
|
||||
717
README.md
717
README.md
|
|
@ -1,85 +1,644 @@
|
|||
# General Bots Workspace
|
||||
|
||||
**Version:** 6.1.0
|
||||
## ⚠️ CRITICAL SECURITY WARNING
|
||||
|
||||
**NEVER CREATE FILES WITH SECRETS IN THE REPOSITORY ROOT**
|
||||
|
||||
Secret files MUST be placed in `/tmp/` only:
|
||||
- ✅ `/tmp/vault-token-gb` - Vault root token
|
||||
- ✅ `/tmp/vault-unseal-key-gb` - Vault unseal key
|
||||
- ❌ `vault-unseal-keys` - FORBIDDEN (tracked by git)
|
||||
- ❌ `start-and-unseal.sh` - FORBIDDEN (contains secrets)
|
||||
|
||||
**Files added to .gitignore:** `vault-unseal-keys`, `start-and-unseal.sh`, `vault-token-*`
|
||||
|
||||
**Why `/tmp/`?**
|
||||
- Cleared on reboot (ephemeral)
|
||||
- Not tracked by git
|
||||
- Standard Unix security practice
|
||||
- Prevents accidental commits
|
||||
|
||||
---
|
||||
|
||||
|
||||
**Version:** 6.3.0
|
||||
**Type:** Rust Workspace (Monorepo with Independent Subproject Repos)
|
||||
|
||||
---
|
||||
|
||||
## Structure
|
||||
## Overview
|
||||
|
||||
This workspace contains multiple General Bots projects:
|
||||
General Bots is a comprehensive automation platform built with Rust, providing a unified workspace for building AI-powered bots, web interfaces, desktop applications, and integration tools. The workspace follows a modular architecture with independent subprojects that can be developed and deployed separately while sharing common libraries and standards.
|
||||
|
||||
For comprehensive documentation, see **[docs.pragmatismo.com.br](https://docs.pragmatismo.com.br)** or the **[BotBook](./botbook)** for detailed guides, API references, and tutorials.
|
||||
|
||||
---
|
||||
|
||||
## 📁 Workspace Structure
|
||||
|
||||
| Crate | Purpose | Port | Tech Stack |
|
||||
|-------|---------|------|------------|
|
||||
| **botserver** | Main API server, business logic | 9000 | Axum, Diesel, Rhai BASIC |
|
||||
| **botui** | Web UI server (dev) + proxy | 3000 | Axum, HTML/HTMX/CSS |
|
||||
| **botapp** | Desktop app wrapper | - | Tauri 2 |
|
||||
| **botlib** | Shared library | - | Core types, errors |
|
||||
| **botbook** | Documentation | - | mdBook |
|
||||
| **bottest** | Integration tests | - | tokio-test |
|
||||
| **botdevice** | IoT/Device support | - | Rust |
|
||||
| **botmodels** | Data models visualization | - | - |
|
||||
| **botplugin** | Browser extension | - | JS |
|
||||
|
||||
### Key Paths
|
||||
- **Binary:** `target/debug/botserver`
|
||||
- **Run from:** `botserver/` directory
|
||||
- **Env file:** `botserver/.env`
|
||||
- **Stack:** `botserver-stack/`
|
||||
- **UI Files:** `botui/ui/suite/`
|
||||
- **Local Bot Data:** `/opt/gbo/data/` (place `.gbai` packages here)
|
||||
|
||||
### Local Bot Data Directory
|
||||
|
||||
Place local bot packages in `/opt/gbo/data/` for automatic loading and monitoring:
|
||||
|
||||
**Directory Structure:**
|
||||
```
|
||||
gb/
|
||||
├── PROMPT.md ← Workspace-level development guide (READ THIS FIRST)
|
||||
├── Cargo.toml ← Workspace configuration
|
||||
├── README.md ← This file
|
||||
│
|
||||
├── botapp/ ← Desktop application (Tauri)
|
||||
├── botserver/ ← Main server (API + business logic)
|
||||
├── botlib/ ← Shared library (types, utilities)
|
||||
├── botui/ ← Web UI (HTML/CSS/JS)
|
||||
├── botbook/ ← Documentation
|
||||
├── bottest/ ← Integration tests
|
||||
├── botdevice/ ← Device integration
|
||||
├── botmodels/ ← AI models
|
||||
├── botplugin/ ← Plugin system
|
||||
├── bottemplates/ ← Templates
|
||||
└── target/ ← Build artifacts
|
||||
/opt/gbo/data/
|
||||
└── mybot.gbai/
|
||||
├── mybot.gbdialog/
|
||||
│ ├── start.bas
|
||||
│ └── main.bas
|
||||
└── mybot.gbot/
|
||||
└── config.csv
|
||||
```
|
||||
|
||||
**Features:**
|
||||
- **Auto-loading:** Bots automatically mounted on server startup
|
||||
- **Auto-compilation:** `.bas` files compiled to `.ast` on change
|
||||
- **Auto-creation:** New bots automatically added to database
|
||||
- **Hot-reload:** Changes trigger immediate recompilation
|
||||
- **Monitored by:** LocalFileMonitor and ConfigWatcher services
|
||||
|
||||
**Usage:**
|
||||
1. Create bot directory structure in `/opt/gbo/data/`
|
||||
2. Add `.bas` files to `<bot_name>.gbai/<bot_name>.gbdialog/`
|
||||
3. Server automatically detects and loads the bot
|
||||
4. Optional: Add `config.csv` for bot configuration
|
||||
|
||||
---
|
||||
|
||||
## 🏗️ BotServer Component Architecture
|
||||
|
||||
### 🔧 Infrastructure Components (Auto-Managed)
|
||||
|
||||
BotServer automatically installs, configures, and manages all infrastructure components on first run. **DO NOT manually start these services** - BotServer handles everything.
|
||||
|
||||
**Automatic Service Lifecycle:**
|
||||
1. **Start**: When botserver starts, it automatically launches all infrastructure components (PostgreSQL, Vault, MinIO, Valkey, Qdrant, etc.)
|
||||
2. **Credentials**: BotServer retrieves all service credentials (passwords, tokens, API keys) from Vault
|
||||
3. **Connection**: BotServer uses these credentials to establish secure connections to each service
|
||||
4. **Query**: All database queries, cache operations, and storage requests are authenticated using Vault-managed credentials
|
||||
|
||||
**Credential Flow:**
|
||||
```
|
||||
botserver starts
|
||||
↓
|
||||
Launch PostgreSQL, MinIO, Valkey, Qdrant
|
||||
↓
|
||||
Connect to Vault
|
||||
↓
|
||||
Retrieve service credentials (from database)
|
||||
↓
|
||||
Authenticate with each service using retrieved credentials
|
||||
↓
|
||||
Ready to handle requests
|
||||
```
|
||||
|
||||
| Component | Purpose | Port | Binary Location | Credentials From |
|
||||
|-----------|---------|------|-----------------|------------------|
|
||||
| **Vault** | Secrets management | 8200 | `botserver-stack/bin/vault/vault` | Auto-unsealed |
|
||||
| **PostgreSQL** | Primary database | 5432 | `botserver-stack/bin/tables/bin/postgres` | Vault → database |
|
||||
| **MinIO** | Object storage (S3-compatible) | 9000/9001 | `botserver-stack/bin/drive/minio` | Vault → database |
|
||||
| **Zitadel** | Identity/Authentication | 8300 | `botserver-stack/bin/directory/zitadel` | Vault → database |
|
||||
| **Qdrant** | Vector database (embeddings) | 6333 | `botserver-stack/bin/vector_db/qdrant` | Vault → database |
|
||||
| **Valkey** | Cache/Queue (Redis-compatible) | 6379 | `botserver-stack/bin/cache/valkey-server` | Vault → database |
|
||||
| **Llama.cpp** | Local LLM server | 8081 | `botserver-stack/bin/llm/build/bin/llama-server` | Vault → database |
|
||||
|
||||
### 📦 Component Installation System
|
||||
|
||||
Components are defined in `botserver/3rdparty.toml` and managed by the `PackageManager` (`botserver/src/core/package_manager/`):
|
||||
|
||||
```toml
|
||||
[components.cache]
|
||||
name = "Valkey Cache (Redis-compatible)"
|
||||
url = "https://github.com/valkey-io/valkey/archive/refs/tags/8.0.2.tar.gz"
|
||||
filename = "valkey-8.0.2.tar.gz"
|
||||
|
||||
[components.llm]
|
||||
name = "Llama.cpp Server"
|
||||
url = "https://github.com/ggml-org/llama.cpp/releases/download/b7345/llama-b7345-bin-ubuntu-x64.zip"
|
||||
filename = "llama-b7345-bin-ubuntu-x64.zip"
|
||||
```
|
||||
|
||||
**Installation Flow:**
|
||||
1. **Download:** Components downloaded to `botserver-installers/` (cached)
|
||||
2. **Extract/Build:** Binaries placed in `botserver-stack/bin/<component>/`
|
||||
3. **Configure:** Config files generated in `botserver-stack/conf/<component>/`
|
||||
4. **Start:** Components started with proper TLS certificates
|
||||
5. **Monitor:** Components monitored and auto-restarted if needed
|
||||
|
||||
**Bootstrap Process:**
|
||||
- First run: Full bootstrap (downloads, installs, configures all components)
|
||||
- Subsequent runs: Only starts existing components (uses cached binaries)
|
||||
- Config stored in: `botserver-stack/conf/system/bootstrap.json`
|
||||
|
||||
### 🚀 PROPER STARTUP PROCEDURES
|
||||
|
||||
**❌ FORBIDDEN:**
|
||||
- NEVER manually start infrastructure components (Vault, PostgreSQL, MinIO, etc.)
|
||||
- NEVER run `cargo run` or `cargo build` for botserver directly without ./restart.sh
|
||||
- NEVER modify botserver-stack/ files manually (use botserver API)
|
||||
|
||||
**✅ REQUIRED:**
|
||||
|
||||
**Option 1: Development (Recommended)**
|
||||
```bash
|
||||
./restart.sh
|
||||
```
|
||||
This script:
|
||||
1. Kills existing processes cleanly
|
||||
2. Builds botserver and botui sequentially (no race conditions)
|
||||
3. Starts botserver in background with logging to `botserver.log`
|
||||
4. Starts botui in background with logging to `botui.log`
|
||||
5. Shows process IDs and access URLs
|
||||
|
||||
**Option 2: Production/Release**
|
||||
```bash
|
||||
# Build release binary first
|
||||
cargo build --release -p botserver
|
||||
|
||||
# Start with release binary
|
||||
RUST_LOG=info ./target/release/botserver --noconsole 2>&1 | tee botserver.log &
|
||||
```
|
||||
|
||||
**Option 3: Using Exec (Systemd/Supervisord)**
|
||||
```bash
|
||||
# In systemd service or similar
|
||||
ExecStart=/home/rodriguez/src/gb/target/release/botserver --noconsole
|
||||
```
|
||||
|
||||
### 🔒 Component Communication
|
||||
|
||||
All components communicate through internal networks with mTLS:
|
||||
- **Vault**: mTLS for secrets access
|
||||
- **PostgreSQL**: TLS encrypted connections
|
||||
- **MinIO**: TLS with client certificates
|
||||
- **Zitadel**: mTLS for user authentication
|
||||
|
||||
Certificates auto-generated in: `botserver-stack/conf/system/certificates/`
|
||||
|
||||
### 📊 Component Status
|
||||
|
||||
Check component status anytime:
|
||||
```bash
|
||||
# Check if all components are running
|
||||
ps aux | grep -E "vault|postgres|minio|zitadel|qdrant|valkey" | grep -v grep
|
||||
|
||||
# View component logs
|
||||
tail -f botserver-stack/logs/vault/vault.log
|
||||
tail -f botserver-stack/logs/tables/postgres.log
|
||||
tail -f botserver-stack/logs/drive/minio.log
|
||||
|
||||
# Test component connectivity
|
||||
cd botserver-stack/bin/vault && ./vault status
|
||||
cd botserver-stack/bin/cache && ./valkey-cli ping
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## CRITICAL: PROMPT.md Files
|
||||
## 🏗️ Component Dependency Graph
|
||||
|
||||
**Each project has a PROMPT.md that defines its development rules.**
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Client Layer │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ botui (Web UI) │ botapp (Desktop) │ botplugin (Ext) │
|
||||
│ HTMX + Axum │ Tauri 2 Wrapper │ Browser Extension │
|
||||
└─────────┬───────────────────┬──────────────────┬─────────────────┘
|
||||
│ │ │
|
||||
└───────────────────┼──────────────────┘
|
||||
│
|
||||
┌─────────▼─────────┐
|
||||
│ botlib │
|
||||
│ (Shared Types) │
|
||||
└─────────┬─────────┘
|
||||
│
|
||||
┌───────────────────┼───────────────────┐
|
||||
│ │ │
|
||||
┌─────▼─────┐ ┌─────▼─────┐ ┌─────▼─────┐
|
||||
│ botserver │ │ bottest │ │ botdevice │
|
||||
│ API Core │ │ Tests │ │ IoT/Device │
|
||||
└───────────┘ └───────────┘ └───────────┘
|
||||
```
|
||||
|
||||
The diagnostics tool reads and respects these PROMPT.md files.
|
||||
### Dependency Rules
|
||||
|
||||
### Hierarchy
|
||||
| Crate | Depends On | Why |
|
||||
|-------|-----------|-----|
|
||||
| **botserver** | botlib | Shared types, error handling, models |
|
||||
| **botui** | botlib | Common data structures, API client |
|
||||
| **botapp** | botlib | Shared types, desktop-specific utilities |
|
||||
| **bottest** | botserver, botlib | Integration testing with real components |
|
||||
| **botdevice** | botlib | Device types, communication protocols |
|
||||
| **botplugin** | - | Standalone browser extension (JS) |
|
||||
|
||||
1. **`PROMPT.md`** (this directory) - Workspace-wide rules
|
||||
2. **`botapp/PROMPT.md`** - Desktop app specifics
|
||||
3. **`botserver/PROMPT.md`** - Server specifics
|
||||
4. **`botlib/PROMPT.md`** - Library specifics
|
||||
5. **`botui/PROMPT.md`** - UI specifics
|
||||
6. **`botbook/PROMPT.md`** - Documentation specifics
|
||||
7. **`bottest/PROMPT.md`** - Test specifics
|
||||
**Key Principle:** `botlib` contains ONLY shared types and utilities. No business logic. All business logic lives in botserver or specialized crates.
|
||||
|
||||
**ALWAYS read the relevant PROMPT.md before working on a project.**
|
||||
## 📦 Module Responsibility Matrix
|
||||
|
||||
---
|
||||
### botserver/src/ Module Structure
|
||||
|
||||
## Main Directive
|
||||
| Module | Responsibility | Key Types | Dependencies |
|
||||
|--------|---------------|-----------|--------------|
|
||||
| **core/bot/** | WebSocket handling, bot orchestration | BotOrchestrator, UserMessage | basic, shared |
|
||||
| **core/session/** | Session management, conversation history | SessionManager, UserSession | shared, database |
|
||||
| **basic/** | Rhai BASIC scripting engine | ScriptService, Engine | rhai, keywords |
|
||||
| **basic/keywords/** | BASIC keyword implementations (TALK, HEAR, etc.) | Keyword functions | basic, state |
|
||||
| **llm/** | Multi-vendor LLM API integration | LLMClient, ModelConfig | reqwest, shared |
|
||||
| **drive/** | S3 file storage and monitoring | DriveMonitor, compile_tool | s3, basic |
|
||||
| **security/** | Security guards (command, SQL, error) | SafeCommand, ErrorSanitizer | state |
|
||||
| **shared/** | Database models, schema definitions | Bot, Session, Message | diesel |
|
||||
| **tasks/** | AutoTask execution system | TaskRunner, TaskScheduler | core/basic |
|
||||
| **auto_task/** | LLM-powered app generation | AppGenerator, template engine | llm, tasks |
|
||||
| **learn/** | Knowledge base management | KBManager, vector storage | database, drive |
|
||||
| **attendance/** | LLM-assisted customer service | AttendantManager, queue | core/bot |
|
||||
|
||||
**LOOP AND COMPACT UNTIL 0 WARNINGS - MAXIMUM YOLO**
|
||||
### Data Flow Patterns
|
||||
|
||||
- 0 warnings
|
||||
- 0 errors
|
||||
- Trust project diagnostics
|
||||
- Respect all rules
|
||||
- No `#[allow()]` in source code
|
||||
- Real code fixes only
|
||||
```
|
||||
1. User Request Flow:
|
||||
Client → WebSocket → botserver/src/core/bot/mod.rs
|
||||
↓
|
||||
BotOrchestrator::stream_response()
|
||||
↓
|
||||
┌───────────┴───────────┐
|
||||
│ │
|
||||
LLM API Call Script Execution
|
||||
(llm/mod.rs) (basic/mod.rs)
|
||||
│ │
|
||||
└───────────┬───────────┘
|
||||
↓
|
||||
Response → WebSocket → Client
|
||||
|
||||
2. File Sync Flow:
|
||||
S3 Drive → drive_monitor/src/drive_monitor/mod.rs
|
||||
↓
|
||||
Download .bas files
|
||||
↓
|
||||
compile_file() → Generate .ast
|
||||
↓
|
||||
Store in ./work/{bot_name}.gbai/
|
||||
|
||||
3. Script Execution Flow:
|
||||
.bas file → ScriptService::compile()
|
||||
↓
|
||||
preprocess_basic_script()
|
||||
↓
|
||||
engine.compile() → AST
|
||||
↓
|
||||
ScriptService::run() → Execute
|
||||
↓
|
||||
TALK commands → WebSocket messages
|
||||
```
|
||||
|
||||
### Common Architectural Patterns
|
||||
|
||||
| Pattern | Where Used | Purpose |
|
||||
|---------|-----------|---------|
|
||||
| **State via Arc<AppState>** | All handlers | Shared async state (DB, cache, config) |
|
||||
| **Extension(state) extractor** | Axum handlers | Inject Arc<AppState> into route handlers |
|
||||
| **tokio::spawn_blocking** | CPU-intensive tasks | Offload blocking work from async runtime |
|
||||
| **WebSocket with split()** | Real-time comms | Separate sender/receiver for WS streams |
|
||||
| **ErrorSanitizer for responses** | All HTTP errors | Prevent leaking sensitive info in errors |
|
||||
| **SafeCommand for execution** | Command running | Whitelist-based command validation |
|
||||
| **Rhai for scripting** | BASIC interpreter | Embeddable scripting language |
|
||||
| **Diesel ORM** | Database access | Type-safe SQL queries |
|
||||
| **Redis for cache** | Session data | Fast key-value storage |
|
||||
| **S3 for storage** | File system | Scalable object storage |
|
||||
|
||||
---
|
||||
|
||||
## Quick Start
|
||||
|
||||
### 🚀 Simple Startup (ALWAYS USE restart.sh)
|
||||
|
||||
```bash
|
||||
./restart.sh
|
||||
```
|
||||
|
||||
**⚠️ CRITICAL: ALWAYS use restart.sh - NEVER start servers individually!**
|
||||
|
||||
The script handles BOTH servers properly:
|
||||
1. Stop existing processes cleanly
|
||||
2. Build botserver and botui sequentially (no race conditions)
|
||||
3. Start botserver in background → **automatically starts all infrastructure services (PostgreSQL, Vault, MinIO, Valkey, Qdrant)**
|
||||
4. BotServer retrieves credentials from Vault and authenticates with all services
|
||||
5. Start botui in background → proxy to botserver
|
||||
6. Show process IDs and monitoring commands
|
||||
|
||||
**Infrastructure services are fully automated - no manual configuration required!**
|
||||
|
||||
**Monitor startup:**
|
||||
```bash
|
||||
tail -f botserver.log botui.log
|
||||
```
|
||||
|
||||
**Access:**
|
||||
- Web UI: http://localhost:3000
|
||||
- API: http://localhost:9000
|
||||
|
||||
### 📊 Monitor & Debug
|
||||
|
||||
```bash
|
||||
tail -f botserver.log botui.log
|
||||
```
|
||||
|
||||
**Quick status check:**
|
||||
```bash
|
||||
ps aux | grep -E "botserver|botui" | grep -v grep
|
||||
```
|
||||
|
||||
**Quick error scan:**
|
||||
```bash
|
||||
grep -E " E |W |CLIENT:" botserver.log | tail -20
|
||||
```
|
||||
|
||||
### 🔧 Manual Startup (If needed)
|
||||
|
||||
**⚠️ WARNING: Only use if restart.sh fails. Always prefer restart.sh!**
|
||||
|
||||
```bash
|
||||
cd botserver && cargo run -- --noconsole > ../botserver.log 2>&1 &
|
||||
cd botui && BOTSERVER_URL="http://localhost:9000" cargo run > ../botui.log 2>&1 &
|
||||
```
|
||||
|
||||
### 🛑 Stop Servers
|
||||
|
||||
```bash
|
||||
pkill -f botserver; pkill -f botui
|
||||
```
|
||||
|
||||
### ⚠️ Common Issues
|
||||
|
||||
**Vault init error?** Delete stale state:
|
||||
```bash
|
||||
rm -rf botserver-stack/data/vault botserver-stack/conf/vault/init.json && ./restart.sh
|
||||
```
|
||||
|
||||
**Port in use?** Find and kill:
|
||||
```bash
|
||||
lsof -ti:9000 | xargs kill -9
|
||||
lsof -ti:3000 | xargs kill -9
|
||||
```
|
||||
|
||||
**⚠️ IMPORTANT: Stack Services Management**
|
||||
All infrastructure services (PostgreSQL, Vault, Redis, Qdrant, MinIO, etc.) are **automatically started by botserver** and managed through `botserver-stack/` directory, NOT global system installations. The system uses:
|
||||
|
||||
- **Local binaries:** `botserver-stack/bin/` (PostgreSQL, Vault, Redis, etc.)
|
||||
- **Configurations:** `botserver-stack/conf/`
|
||||
- **Data storage:** `botserver-stack/data/`
|
||||
- **Service logs:** `botserver-stack/logs/` (check here for troubleshooting)
|
||||
- **Credentials:** Stored in Vault, retrieved by botserver at startup
|
||||
|
||||
**Do NOT install or reference global PostgreSQL, Redis, or other services.** When botserver starts, it automatically:
|
||||
1. Launches all required stack services
|
||||
2. Connects to Vault
|
||||
3. Retrieves credentials from the `bot_configuration` database table
|
||||
4. Authenticates with each service using retrieved credentials
|
||||
5. Begins handling requests with authenticated connections
|
||||
|
||||
If you encounter service errors, check the individual service logs in `./botserver-stack/logs/[service]/` directories.
|
||||
|
||||
### UI File Deployment - Production Options
|
||||
|
||||
**Option 1: Embedded UI (Recommended for Production)**
|
||||
|
||||
The `embed-ui` feature compiles UI files directly into the botui binary, eliminating the need for separate file deployment:
|
||||
|
||||
```bash
|
||||
# Build with embedded UI files
|
||||
cargo build --release -p botui --features embed-ui
|
||||
|
||||
# The binary now contains all UI files - no additional deployment needed!
|
||||
# The botui binary is self-contained and production-ready
|
||||
```
|
||||
|
||||
**Benefits of embed-ui:**
|
||||
- ✅ Single binary deployment (no separate UI files)
|
||||
- ✅ Faster startup (no filesystem access)
|
||||
- ✅ Smaller attack surface
|
||||
- ✅ Simpler deployment process
|
||||
|
||||
**Option 2: Filesystem Deployment (Development Only)**
|
||||
|
||||
For development, UI files are served from the filesystem:
|
||||
|
||||
```bash
|
||||
# UI files must exist at botui/ui/suite/
|
||||
# This is automatically available in development builds
|
||||
```
|
||||
|
||||
**Option 3: Manual File Deployment (Legacy)**
|
||||
|
||||
If you need to deploy UI files separately (not recommended):
|
||||
|
||||
```bash
|
||||
# Deploy UI files to production location
|
||||
./botserver/deploy/deploy-ui.sh /opt/gbo
|
||||
|
||||
# Verify deployment
|
||||
ls -la /opt/gbo/bin/ui/suite/index.html
|
||||
```
|
||||
|
||||
See `botserver/deploy/README.md` for deployment scripts.
|
||||
|
||||
### Start Both Servers (Automated)
|
||||
```bash
|
||||
# Use restart script (RECOMMENDED)
|
||||
./restart.sh
|
||||
```
|
||||
|
||||
### Start Both Servers (Manual)
|
||||
```bash
|
||||
# Terminal 1: botserver
|
||||
cd botserver && cargo run -- --noconsole
|
||||
|
||||
# Terminal 2: botui
|
||||
cd botui && BOTSERVER_URL="http://localhost:9000" cargo run
|
||||
```
|
||||
|
||||
### Build Commands
|
||||
```bash
|
||||
# Check single crate
|
||||
cargo check -p botserver
|
||||
|
||||
# Build workspace
|
||||
cargo build
|
||||
cargo test
|
||||
|
||||
# Run tests
|
||||
cargo test -p bottest
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Development Workflow
|
||||
## 🤖 AI Agent Guidelines
|
||||
|
||||
1. Read `PROMPT.md` (workspace-level rules)
|
||||
2. Read `<project>/PROMPT.md` (project-specific rules)
|
||||
3. Use diagnostics tool to check warnings
|
||||
4. Fix all warnings with full file rewrites
|
||||
5. Verify with diagnostics after each file
|
||||
6. Never suppress warnings with `#[allow()]`
|
||||
> **For LLM instructions, coding rules, security directives, testing workflows, and error handling patterns, see [AGENTS.md](./AGENTS.md).**
|
||||
|
||||
---
|
||||
|
||||
## 📖 Glossary
|
||||
|
||||
| Term | Definition | Usage |
|
||||
|------|-----------|-------|
|
||||
| **Bot** | AI agent with configuration, scripts, and knowledge bases | Primary entity in system |
|
||||
| **Session** | Single conversation instance between user and bot | Stored in `sessions` table |
|
||||
| **Dialog** | Collection of BASIC scripts (.bas files) for bot logic | Stored in `{bot_name}.gbdialog/` |
|
||||
| **Tool** | Reusable function callable by LLM | Defined in .bas files, compiled to .ast |
|
||||
| **Knowledge Base (KB)** | Vector database of documents for semantic search | Managed in `learn/` module |
|
||||
| **Scheduler** | Time-triggered task execution | Cron-like scheduling in BASIC scripts |
|
||||
| **Drive** | S3-compatible storage for files | Abstracted in `drive/` module |
|
||||
| **Rhai** | Embedded scripting language for BASIC dialect | Rhai engine in `basic/` module |
|
||||
| **WebSocket Adapter** | Component that sends messages to connected clients | `web_adapter` in state |
|
||||
| **AutoTask** | LLM-generated task automation system | In `auto_task/` and `tasks/` modules |
|
||||
| **Orchestrator** | Coordinates LLM, tools, KBs, and user input | `BotOrchestrator` in `core/bot/` |
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
## 🖥️ UI Architecture (botui + botserver)
|
||||
|
||||
### Two Servers During Development
|
||||
|
||||
| Server | Port | Purpose |
|
||||
|--------|------|---------|
|
||||
| **botui** | 3000 | Serves UI files + proxies API to botserver |
|
||||
| **botserver** | 9000 | Backend API + embedded UI fallback |
|
||||
|
||||
### How It Works
|
||||
|
||||
```
|
||||
Browser → localhost:3000 → botui (serves HTML/CSS/JS)
|
||||
→ /api/* proxied to botserver:9000
|
||||
→ /suite/* served from botui/ui/suite/
|
||||
```
|
||||
|
||||
### Adding New Suite Apps
|
||||
|
||||
1. Create folder: `botui/ui/suite/<appname>/`
|
||||
2. Add to `SUITE_DIRS` in `botui/src/ui_server/mod.rs`
|
||||
3. Rebuild botui: `cargo build -p botui`
|
||||
4. Add menu entry in `botui/ui/suite/index.html`
|
||||
|
||||
### Hot Reload
|
||||
|
||||
- **UI files (HTML/CSS/JS)**: Edit & refresh browser (no restart)
|
||||
- **botui Rust code**: Rebuild + restart botui
|
||||
- **botserver Rust code**: Rebuild + restart botserver
|
||||
|
||||
### Production (Single Binary)
|
||||
|
||||
When `botui/ui/suite/` folder not found, botserver uses **embedded UI** compiled into binary via `rust-embed`.
|
||||
|
||||
---
|
||||
|
||||
## 🎨 Frontend Standards
|
||||
|
||||
### HTMX-First Approach
|
||||
- Use HTMX to minimize JavaScript
|
||||
- Server returns HTML fragments, not JSON
|
||||
- Use `hx-get`, `hx-post`, `hx-target`, `hx-swap`
|
||||
- WebSocket via htmx-ws extension
|
||||
|
||||
### Local Assets Only - NO CDN
|
||||
```html
|
||||
<!-- ✅ CORRECT -->
|
||||
<script src="js/vendor/htmx.min.js"></script>
|
||||
|
||||
<!-- ❌ WRONG -->
|
||||
<script src="https://unpkg.com/htmx.org@1.9.10"></script>
|
||||
```
|
||||
|
||||
### Vendor Libraries Location
|
||||
```
|
||||
ui/suite/js/vendor/
|
||||
├── htmx.min.js
|
||||
├── htmx-ws.js
|
||||
├── marked.min.js
|
||||
└── gsap.min.js
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📋 Project-Specific Guidelines
|
||||
|
||||
Each crate has its own README.md with specific guidelines:
|
||||
|
||||
| Crate | README.md Location | Focus |
|
||||
|-------|-------------------|-------|
|
||||
| botserver | `botserver/README.md` | API, security, Rhai BASIC |
|
||||
| botui | `botui/README.md` | UI, HTMX, CSS design system |
|
||||
| botapp | `botapp/README.md` | Tauri, desktop features |
|
||||
| botlib | `botlib/README.md` | Shared types, errors |
|
||||
| botbook | `botbook/README.md` | Documentation, mdBook |
|
||||
| bottest | `bottest/README.md` | Test infrastructure |
|
||||
|
||||
### Special Prompts
|
||||
| File | Purpose |
|
||||
|------|---------|
|
||||
| `botserver/src/tasks/README.md` | AutoTask LLM executor |
|
||||
| `botserver/src/auto_task/APP_GENERATOR_PROMPT.md` | App generation |
|
||||
|
||||
---
|
||||
|
||||
## 📚 Documentation
|
||||
|
||||
For complete documentation, guides, and API references:
|
||||
|
||||
- **[docs.pragmatismo.com.br](https://docs.pragmatismo.com.br)** - Full online documentation
|
||||
- **[BotBook](./botbook)** - Local comprehensive guide with tutorials and examples
|
||||
- **[General Bots Repository](https://github.com/GeneralBots/BotServer)** - Main project repository
|
||||
|
||||
---
|
||||
|
||||
## 🔧 Immediate Technical Debt
|
||||
|
||||
### Critical Issues to Address
|
||||
|
||||
1. **Error Handling Debt**: 955 instances of `unwrap()`/`expect()` in production code
|
||||
2. **Performance Debt**: 12,973 excessive `clone()`/`to_string()` calls
|
||||
3. **File Size Debt**: 7 files exceed 450 lines (largest: 3220 lines)
|
||||
4. **Test Coverage**: Missing integration tests for critical paths
|
||||
5. **Documentation**: Missing inline documentation for complex algorithms
|
||||
|
||||
### Weekly Maintenance Tasks
|
||||
|
||||
```bash
|
||||
# Check for duplicate dependencies
|
||||
cargo tree --duplicates
|
||||
|
||||
# Remove unused dependencies
|
||||
cargo machete
|
||||
|
||||
# Check binary size
|
||||
cargo build --release && ls -lh target/release/botserver
|
||||
|
||||
# Performance profiling
|
||||
cargo bench
|
||||
|
||||
# Security audit
|
||||
cargo audit
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -87,42 +646,56 @@ cargo test
|
|||
|
||||
**Note:** Each subproject has its own git repository. This root repository only tracks workspace-level files:
|
||||
|
||||
- `PROMPT.md` - Development guide
|
||||
- `Cargo.toml` - Workspace configuration
|
||||
- `README.md` - This file
|
||||
- `.gitignore` - Ignore patterns
|
||||
- `ADDITIONAL-SUGGESTIONS.md` - Enhancement ideas
|
||||
- `TODO-*.md` - Task tracking files
|
||||
|
||||
Subprojects (botapp, botserver, etc.) are **not** git submodules - they are independent repositories.
|
||||
Subprojects (botapp, botserver, botui, etc.) are **independent repositories referenced as git submodules**.
|
||||
|
||||
### ⚠️ CRITICAL: Submodule Push Workflow
|
||||
|
||||
When making changes to any submodule (botserver, botui, botlib, etc.):
|
||||
|
||||
1. **Commit and push changes within the submodule directory:**
|
||||
```bash
|
||||
cd botserver
|
||||
git add .
|
||||
git commit -m "Your changes"
|
||||
git push pragmatismo main
|
||||
git push github main
|
||||
```
|
||||
|
||||
2. **Update the global gb repository submodule reference:**
|
||||
```bash
|
||||
cd .. # Back to gb root
|
||||
git add botserver
|
||||
git commit -m "Update botserver submodule to latest commit"
|
||||
git push pragmatismo main
|
||||
git push github main
|
||||
```
|
||||
|
||||
**Failure to push the global gb repository will cause submodule changes to not trigger CI/CD pipelines.**
|
||||
|
||||
Both repositories must be pushed for changes to take effect in production.
|
||||
|
||||
---
|
||||
|
||||
## Rules Summary
|
||||
## Development Workflow
|
||||
|
||||
```
|
||||
✅ FULL FILE REWRITES ONLY
|
||||
✅ BATCH ALL FIXES BEFORE WRITING
|
||||
✅ VERIFY WITH DIAGNOSTICS AFTER EACH FILE
|
||||
✅ TRUST PROJECT DIAGNOSTICS
|
||||
✅ RESPECT ALL RULES
|
||||
|
||||
❌ NEVER use #[allow()] in source code
|
||||
❌ NEVER use partial edits
|
||||
❌ NEVER run cargo check/clippy manually
|
||||
❌ NEVER leave unused code
|
||||
❌ NEVER use .unwrap()/.expect()
|
||||
❌ NEVER use panic!/todo!/unimplemented!()
|
||||
❌ NEVER add comments
|
||||
```
|
||||
1. Read this README.md (workspace structure)
|
||||
2. Read **[AGENTS.md](./AGENTS.md)** (coding rules & workflows)
|
||||
3. **BEFORE creating any .md file, search botbook/ for existing documentation**
|
||||
4. Read `<project>/README.md` (project-specific rules)
|
||||
5. Use diagnostics tool to check warnings
|
||||
6. Fix all warnings with full file rewrites
|
||||
7. Verify with diagnostics after each file
|
||||
8. Never suppress warnings with `#[allow()]`
|
||||
|
||||
---
|
||||
|
||||
## Links
|
||||
|
||||
- Main Server: http://localhost:8081
|
||||
- Desktop App: Uses Tauri to wrap botui
|
||||
- Documentation: See botbook/
|
||||
|
||||
---
|
||||
|
||||
## License
|
||||
|
||||
|
|
|
|||
2
botapp
2
botapp
|
|
@ -1 +1 @@
|
|||
Subproject commit 1a1e17fa1012e4db10a0f716c9b63a03b4863c9f
|
||||
Subproject commit 0b556948f970832e8606f886853793e2bc8dc35c
|
||||
2
botbook
2
botbook
|
|
@ -1 +1 @@
|
|||
Subproject commit 827e011ac05084396aaf2c3098409bf5e02b5cf9
|
||||
Subproject commit 82a236f369e58fe0eda4df704b9ee74a725874e8
|
||||
|
|
@ -1 +1 @@
|
|||
Subproject commit 97778e06dd804be55ff761c7fe2788af0ef50626
|
||||
Subproject commit 35411f4f9e64e54b1039360ab654d537cd2958c9
|
||||
2
botlib
2
botlib
|
|
@ -1 +1 @@
|
|||
Subproject commit bfaa68dc35e96ced2915d43ffe6fca8267a9a598
|
||||
Subproject commit e7caed45a44ab319c64d90f84281dbdbcba905b7
|
||||
|
|
@ -1 +1 @@
|
|||
Subproject commit 462a6dfa51b12f22e87712e613a559f66f9013cb
|
||||
Subproject commit 4518bf7bd1c4ae6fafd5c42fa5f4515a383b480a
|
||||
|
|
@ -1 +1 @@
|
|||
Subproject commit 17a3caebabddbe843c2b7fd93f624b0ccd9c44fb
|
||||
Subproject commit 1727e48307fdb7b54c726af8cd6b12669764e908
|
||||
|
|
@ -1 +1 @@
|
|||
Subproject commit 84458b2a6905af7db72b15f5e833bb7942ccdaa9
|
||||
Subproject commit 2ff68e5a2a24b7b63386efd2e2325d478efbb925
|
||||
|
|
@ -1 +1 @@
|
|||
Subproject commit dd3d8c74dd58a1cc6d6b18d22108819519aaf9c3
|
||||
Subproject commit 3110dd587290047f283300d674ad325f4f9b3046
|
||||
2
bottest
2
bottest
|
|
@ -1 +1 @@
|
|||
Subproject commit 706391b272e0fb7c5b2646cc4cc72180195e07f4
|
||||
Subproject commit 346120cb0b916f72abd2fdad577ae1c606aba1a2
|
||||
2
botui
2
botui
|
|
@ -1 +1 @@
|
|||
Subproject commit 661edc09fa1063673e84b63d2dcb5cfbe0f91232
|
||||
Subproject commit ed4d492e6e7863923491a846a3614de6a6c37946
|
||||
771
crates.tmp
Normal file
771
crates.tmp
Normal file
|
|
@ -0,0 +1,771 @@
|
|||
# BotServer Microservices Partition Plan
|
||||
|
||||
## 🎯 Objective
|
||||
|
||||
Partition the monolithic `botserver` into multiple microservices as separate Rust crates that share state, making the system easier to compile, maintain, and scale.
|
||||
|
||||
## 📊 Current State Analysis
|
||||
|
||||
### Current Structure
|
||||
- **Single monolithic crate**: `botserver` (242 dependencies in Cargo.toml)
|
||||
- **Feature flags**: 50+ features (chat, mail, tasks, drive, llm, etc.)
|
||||
- **Main entry point**: `botserver/src/main.rs` (436 lines)
|
||||
- **Shared state**: `AppState` in `core::shared::state`
|
||||
- **Modules**: 40+ top-level modules
|
||||
|
||||
### Problems with Current Approach
|
||||
1. **Long compile times**: Full rebuilds take 30+ minutes
|
||||
2. **Memory intensive**: Requires significant RAM during compilation
|
||||
3. **Tight coupling**: All modules compiled together
|
||||
4. **Hard to scale**: Can't deploy individual services independently
|
||||
5. **Feature flag complexity**: Many features, hard to test all combinations
|
||||
|
||||
## 🏗️ Proposed Architecture
|
||||
|
||||
### Shared State Architecture
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ SHARED STATE LAYER │
|
||||
│ ┌─────────────────────────────────────────────────────────┐│
|
||||
│ │ botstate (NEW) - Shared state types & interfaces ││
|
||||
│ │ - AppState definition ││
|
||||
│ │ - Database connection pool ││
|
||||
│ │ - Redis/Valkey client ││
|
||||
│ │ - Configuration ││
|
||||
│ │ - LLM provider interface ││
|
||||
│ │ - Secret manager interface ││
|
||||
│ └─────────────────────────────────────────────────────────┘│
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Microservice Crates
|
||||
|
||||
```
|
||||
Workspace Members:
|
||||
├── botlib/ # Existing - Core types, errors, utilities
|
||||
├── botstate/ # NEW - Shared state layer
|
||||
├── botserver-core/ # NEW - Core HTTP server, routing, middleware
|
||||
├── botserver-auth/ # NEW - Authentication & authorization
|
||||
├── botserver-chat/ # NEW - WebSocket chat, LLM integration
|
||||
├── botserver-mail/ # NEW - Email integration (IMAP/SMTP)
|
||||
├── botserver-tasks/ # NEW - Task scheduler, cron jobs
|
||||
├── botserver-drive/ # NEW - File storage (S3/MinIO)
|
||||
├── botserver-llm/ # NEW - LLM providers, embeddings
|
||||
├── botserver-vectordb/ # NEW - Qdrant vector database
|
||||
├── botserver-compliance/# NEW - Legal, audit, compliance
|
||||
├── botserver-video/ # NEW - Video processing, LiveKit
|
||||
├── botserver-contacts/ # NEW - CRM, contacts, calendar
|
||||
├── botserver-auto/ # NEW - Automation, Rhai scripting
|
||||
├── botserver-ui/ # NEW - Embedded UI, TUI (optional)
|
||||
└── botserver/ # EXISTING - Becomes meta-crate that re-exports all
|
||||
```
|
||||
|
||||
## 📦 Detailed Crate Responsibilities
|
||||
|
||||
### 1. **botstate** (NEW - Foundation)
|
||||
**Purpose**: Define shared state types that all services will use
|
||||
|
||||
**Dependencies**:
|
||||
- `botlib` (workspace)
|
||||
- `tokio`, `redis`, `diesel`, `chrono`, `uuid`, `serde`
|
||||
|
||||
**Exports**:
|
||||
```rust
|
||||
pub struct AppState {
|
||||
pub db_pool: PgPool,
|
||||
pub redis_client: Arc<redis::Client>,
|
||||
pub config: Arc<Config>,
|
||||
pub llm_provider: Arc<dyn LLMProvider>,
|
||||
pub secret_manager: Arc<dyn SecretManager>,
|
||||
// ... other shared resources
|
||||
}
|
||||
|
||||
pub trait LLMProvider {
|
||||
async fn generate(&self, prompt: &str) -> Result<String>;
|
||||
}
|
||||
|
||||
pub trait SecretManager {
|
||||
fn get_secret(&self, key: &str) -> Result<String>;
|
||||
}
|
||||
```
|
||||
|
||||
**Location**: `/home/rodriguez/src/gb/botstate/`
|
||||
|
||||
---
|
||||
|
||||
### 2. **botserver-core** (NEW - HTTP Foundation)
|
||||
**Purpose**: Core HTTP server, routing, middleware, health checks
|
||||
|
||||
**Dependencies**:
|
||||
- `botlib`, `botstate`
|
||||
- `axum`, `tower`, `tower-http`, `tokio`
|
||||
|
||||
**Responsibilities**:
|
||||
- HTTP server setup (Axum)
|
||||
- Middleware (CORS, logging, rate limiting)
|
||||
- Health check endpoints
|
||||
- Graceful shutdown
|
||||
- Static file serving
|
||||
|
||||
**Location**: `/home/rodriguez/src/gb/botserver-core/`
|
||||
|
||||
---
|
||||
|
||||
### 3. **botserver-auth** (NEW - Security)
|
||||
**Purpose**: Authentication, authorization, RBAC
|
||||
|
||||
**Dependencies**:
|
||||
- `botlib`, `botstate`, `botserver-core`
|
||||
- `jsonwebtoken`, `argon2`, `axum`
|
||||
|
||||
**Responsibilities**:
|
||||
- User authentication (login/logout)
|
||||
- JWT token management
|
||||
- RBAC (role-based access control)
|
||||
- Session management
|
||||
- OAuth integration
|
||||
|
||||
**Location**: `/home/rodriguez/src/gb/botserver-auth/`
|
||||
|
||||
---
|
||||
|
||||
### 4. **botserver-chat** (NEW - Real-time Communication)
|
||||
**Purpose**: WebSocket chat, message handling, LLM integration
|
||||
|
||||
**Dependencies**:
|
||||
- `botlib`, `botstate`, `botserver-core`
|
||||
- `tokio-tungstenite`, `axum`, `serde_json`
|
||||
|
||||
**Responsibilities**:
|
||||
- WebSocket connections
|
||||
- Message routing
|
||||
- Chat history
|
||||
- Suggestion buttons
|
||||
- Tool execution framework
|
||||
|
||||
**Location**: `/home/rodriguez/src/gb/botserver-chat/`
|
||||
|
||||
---
|
||||
|
||||
### 5. **botserver-mail** (NEW - Email)
|
||||
**Purpose**: Email integration (IMAP/SMTP)
|
||||
|
||||
**Dependencies**:
|
||||
- `botlib`, `botstate`, `botserver-core`
|
||||
- `lettre`, `imap`, `mailparse`
|
||||
|
||||
**Responsibilities**:
|
||||
- IMAP email retrieval
|
||||
- SMTP email sending
|
||||
- Email parsing
|
||||
- Attachments
|
||||
- Email templates
|
||||
|
||||
**Location**: `/home/rodriguez/src/gb/botserver-mail/`
|
||||
|
||||
---
|
||||
|
||||
### 6. **botserver-tasks** (NEW - Scheduling)
|
||||
**Purpose**: Task scheduler, cron jobs
|
||||
|
||||
**Dependencies**:
|
||||
- `botlib`, `botstate`, `botserver-core`
|
||||
- `cron`, `tokio`
|
||||
|
||||
**Responsibilities**:
|
||||
- Cron job scheduler
|
||||
- Task queue management
|
||||
- Recurring tasks
|
||||
- Task execution tracking
|
||||
|
||||
**Location**: `/home/rodriguez/src/gb/botserver-tasks/`
|
||||
|
||||
---
|
||||
|
||||
### 7. **botserver-drive** (NEW - Storage)
|
||||
**Purpose**: File storage (S3/MinIO)
|
||||
|
||||
**Dependencies**:
|
||||
- `botlib`, `botstate`, `botserver-core`
|
||||
- `aws-sdk-s3`, `aws-config`
|
||||
|
||||
**Responsibilities**:
|
||||
- S3/MinIO client
|
||||
- File upload/download
|
||||
- File synchronization
|
||||
- PDF extraction
|
||||
- Document processing
|
||||
|
||||
**Location**: `/home/rodriguez/src/gb/botserver-drive/`
|
||||
|
||||
---
|
||||
|
||||
### 8. **botserver-llm** (NEW - Language Models)
|
||||
**Purpose**: LLM providers, embeddings, caching
|
||||
|
||||
**Dependencies**:
|
||||
- `botlib`, `botstate`
|
||||
- `reqwest`, `serde_json`
|
||||
|
||||
**Responsibilities**:
|
||||
- LLM provider abstraction (Groq, OpenAI, etc.)
|
||||
- Embedding generation
|
||||
- Response caching
|
||||
- Local LLM management (llama.cpp)
|
||||
|
||||
**Location**: `/home/rodriguez/src/gb/botserver-llm/`
|
||||
|
||||
---
|
||||
|
||||
### 9. **botserver-vectordb** (NEW - Vector Database)
|
||||
**Purpose**: Qdrant vector database operations
|
||||
|
||||
**Dependencies**:
|
||||
- `botlib`, `botstate`, `botserver-llm`
|
||||
- `qdrant-client`
|
||||
|
||||
**Responsibilities**:
|
||||
- Vector embeddings storage
|
||||
- Similarity search
|
||||
- Knowledge base chunks
|
||||
- RAG (retrieval-augmented generation)
|
||||
|
||||
**Location**: `/home/rodriguez/src/gb/botserver-vectordb/`
|
||||
|
||||
---
|
||||
|
||||
### 10. **botserver-auto** (NEW - Automation)
|
||||
**Purpose**: Automation, Rhai scripting engine
|
||||
|
||||
**Dependencies**:
|
||||
- `botlib`, `botstate`, `botserver-core`
|
||||
- `rhai`, `tokio`
|
||||
|
||||
**Responsibilities**:
|
||||
- Rhai script engine
|
||||
- BASIC keyword execution
|
||||
- Workflow automation
|
||||
- Event handlers
|
||||
- Script compilation
|
||||
|
||||
**Location**: `/home/rodriguez/src/gb/botserver-auto/`
|
||||
|
||||
---
|
||||
|
||||
### 11. **botserver-contacts** (NEW - CRM)
|
||||
**Purpose**: Contacts, CRM, calendar integration
|
||||
|
||||
**Dependencies**:
|
||||
- `botlib`, `botstate`, `botserver-core`
|
||||
- `icalendar`, `chrono`
|
||||
|
||||
**Responsibilities**:
|
||||
- Contact management
|
||||
- CRM operations
|
||||
- Calendar integration
|
||||
- Google/Microsoft sync
|
||||
|
||||
**Location**: `/home/rodriguez/src/gb/botserver-contacts/`
|
||||
|
||||
---
|
||||
|
||||
### 12. **botserver-compliance** (NEW - Legal)
|
||||
**Purpose**: Legal, audit, compliance
|
||||
|
||||
**Dependencies**:
|
||||
- `botlib`, `botstate`, `botserver-core`
|
||||
- `csv`
|
||||
|
||||
**Responsibilities**:
|
||||
- Audit logging
|
||||
- Compliance reports
|
||||
- Legal document management
|
||||
- Data retention policies
|
||||
|
||||
**Location**: `/home/rodriguez/src/gb/botserver-compliance/`
|
||||
|
||||
---
|
||||
|
||||
### 13. **botserver-video** (NEW - Video)
|
||||
**Purpose**: Video processing, LiveKit integration
|
||||
|
||||
**Dependencies**:
|
||||
- `botlib`, `botstate`, `botserver-core`
|
||||
- `livekit`
|
||||
|
||||
**Responsibilities**:
|
||||
- LiveKit integration
|
||||
- Video analytics
|
||||
- Meeting management
|
||||
- Media processing
|
||||
|
||||
**Location**: `/home/rodriguez/src/gb/botserver-video/`
|
||||
|
||||
---
|
||||
|
||||
### 14. **botserver-ui** (OPTIONAL - TUI)
|
||||
**Purpose**: Console/TUI interface
|
||||
|
||||
**Dependencies**:
|
||||
- `botlib`, `botstate`
|
||||
- `ratatui`, `crossterm`
|
||||
|
||||
**Responsibilities**:
|
||||
- Terminal UI
|
||||
- Progress monitoring
|
||||
- Service status dashboard
|
||||
|
||||
**Location**: `/home/rodriguez/src/gb/botserver-ui/`
|
||||
|
||||
---
|
||||
|
||||
### 15. **botserver** (EXISTING - Meta-crate)
|
||||
**Purpose**: Re-exports all services, maintains backward compatibility
|
||||
|
||||
**Dependencies**:
|
||||
- All botserver-* crates
|
||||
- Feature flags to enable/disable services
|
||||
|
||||
**Responsibilities**:
|
||||
- Re-export all services
|
||||
- Main binary entry point
|
||||
- Feature flag coordination
|
||||
|
||||
**Location**: `/home/rodriguez/src/gb/botserver/` (existing, modified)
|
||||
|
||||
---
|
||||
|
||||
## 🔄 State Sharing Strategy
|
||||
|
||||
### Approach: Shared AppState via botstate Crate
|
||||
|
||||
```rust
|
||||
// botstate/src/lib.rs
|
||||
use redis::Client as RedisClient;
|
||||
use diesel::r2d2::Pool as DbPool;
|
||||
use std::sync::Arc;
|
||||
|
||||
pub struct AppState {
|
||||
pub db_pool: Arc<DbPool>,
|
||||
pub redis_client: Arc<RedisClient>,
|
||||
pub config: Arc<Config>,
|
||||
pub llm_provider: Arc<dyn LLMProvider + Send + Sync>,
|
||||
pub secret_manager: Arc<dyn SecretManager + Send + Sync>,
|
||||
}
|
||||
|
||||
impl AppState {
|
||||
pub fn new(
|
||||
db_pool: DbPool,
|
||||
redis_client: RedisClient,
|
||||
config: Config,
|
||||
llm_provider: Box<dyn LLMProvider + Send + Sync>,
|
||||
secret_manager: Box<dyn SecretManager + Send + Sync>,
|
||||
) -> Self {
|
||||
Self {
|
||||
db_pool: Arc::new(db_pool),
|
||||
redis_client: Arc::new(redis_client),
|
||||
config: Arc::new(config),
|
||||
llm_provider: Arc::from(llm_provider),
|
||||
secret_manager: Arc::from(secret_manager),
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Each Service Gets AppState as Parameter
|
||||
|
||||
```rust
|
||||
// botserver-chat/src/lib.rs
|
||||
use botstate::AppState;
|
||||
use axum::Router;
|
||||
|
||||
pub fn create_router(state: Arc<AppState>) -> Router {
|
||||
Router::new()
|
||||
.route("/ws", websocket_handler)
|
||||
.with_state(state)
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📋 Migration Steps
|
||||
|
||||
### Phase 1: Foundation (Week 1-2)
|
||||
1. ✅ Create `botstate` crate
|
||||
- Extract `AppState` from `botserver`
|
||||
- Define trait interfaces (LLMProvider, SecretManager)
|
||||
- Export shared types
|
||||
|
||||
2. ✅ Create `botserver-core` crate
|
||||
- Extract HTTP server setup
|
||||
- Extract middleware
|
||||
- Extract health checks
|
||||
|
||||
3. ✅ Update workspace `Cargo.toml`
|
||||
- Add new members
|
||||
- Configure dependencies
|
||||
|
||||
### Phase 2: Extract Services (Week 3-6)
|
||||
4. ✅ Extract `botserver-auth`
|
||||
- Move authentication code
|
||||
- Update imports
|
||||
|
||||
5. ✅ Extract `botserver-chat`
|
||||
- Move WebSocket code
|
||||
- Move message handling
|
||||
|
||||
6. ✅ Extract `botserver-mail`
|
||||
- Move email integration
|
||||
- Move IMAP/SMTP code
|
||||
|
||||
7. ✅ Extract `botserver-drive`
|
||||
- Move S3/MinIO code
|
||||
- Move file sync
|
||||
|
||||
8. ✅ Extract `botserver-auto`
|
||||
- Move Rhai engine
|
||||
- Move BASIC keywords
|
||||
|
||||
### Phase 3: Advanced Services (Week 7-10)
|
||||
9. ✅ Extract `botserver-llm`
|
||||
- Move LLM providers
|
||||
- Move caching
|
||||
|
||||
10. ✅ Extract `botserver-vectordb`
|
||||
- Move Qdrant client
|
||||
- Move embeddings
|
||||
|
||||
11. ✅ Extract `botserver-tasks`
|
||||
- Move scheduler
|
||||
- Move cron jobs
|
||||
|
||||
12. ✅ Extract `botserver-contacts`
|
||||
- Move CRM code
|
||||
- Move calendar sync
|
||||
|
||||
13. ✅ Extract `botserver-compliance`
|
||||
- Move audit logging
|
||||
- Move compliance reports
|
||||
|
||||
14. ✅ Extract `botserver-video`
|
||||
- Move LiveKit integration
|
||||
- Move video analytics
|
||||
|
||||
### Phase 4: Integration & Testing (Week 11-12)
|
||||
15. ✅ Update `botserver` as meta-crate
|
||||
- Re-export all services
|
||||
- Maintain backward compatibility
|
||||
- Feature flags coordination
|
||||
|
||||
16. ✅ Test all services independently
|
||||
- Unit tests
|
||||
- Integration tests
|
||||
- End-to-end tests
|
||||
|
||||
17. ✅ Documentation
|
||||
- Update README
|
||||
- Document APIs
|
||||
- Update AGENTS.md
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Benefits
|
||||
|
||||
### Compile Time Improvements
|
||||
- **Before**: Full rebuild 30+ minutes
|
||||
- **After**:
|
||||
- botstate: ~30 seconds
|
||||
- Individual service: 1-3 minutes
|
||||
- Full workspace: Still 30+ minutes (but cached builds work better)
|
||||
|
||||
### Memory Usage
|
||||
- **Before**: 16GB+ RAM required
|
||||
- **After**: 2-4GB per service
|
||||
|
||||
### Development Workflow
|
||||
- Work on single service without rebuilding everything
|
||||
- Better separation of concerns
|
||||
- Easier to test individual components
|
||||
- Can deploy services independently
|
||||
|
||||
### Scalability
|
||||
- Deploy only needed services
|
||||
- Scale services independently
|
||||
- Different services can use different versions of dependencies
|
||||
|
||||
---
|
||||
|
||||
## ⚠️ Challenges & Solutions
|
||||
|
||||
### Challenge 1: Circular Dependencies
|
||||
**Problem**: Services reference each other
|
||||
|
||||
**Solution**:
|
||||
- Use traits in `botstate` for cross-service communication
|
||||
- Dependency injection via `AppState`
|
||||
- Event-driven architecture for loose coupling
|
||||
|
||||
### Challenge 2: Database Migrations
|
||||
**Problem**: Multiple crates need to coordinate migrations
|
||||
|
||||
**Solution**:
|
||||
- Keep all migrations in `botserver` (meta-crate)
|
||||
- Use `diesel_migrations` with centralized migration directory
|
||||
- Each service documents its required migrations
|
||||
|
||||
### Challenge 3: Shared Configuration
|
||||
**Problem**: All services need config values
|
||||
|
||||
**Solution**:
|
||||
- `Config` struct in `botstate`
|
||||
- Loaded once, shared via `Arc<Config>`
|
||||
- Each service reads only what it needs
|
||||
|
||||
### Challenge 4: Feature Flags
|
||||
**Problem**: Complex feature flag interactions
|
||||
|
||||
**Solution**:
|
||||
- Each service has its own feature flags
|
||||
- `botserver` meta-crate coordinates via feature aliases
|
||||
- Default: all services enabled
|
||||
- Can build minimal subset for testing
|
||||
|
||||
---
|
||||
|
||||
## 📊 Dependency Graph
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
botlib[botlib - Core types]
|
||||
botstate[botstate - Shared state]
|
||||
botcore[botserver-core - HTTP server]
|
||||
|
||||
auth[botserver-auth]
|
||||
chat[botserver-chat]
|
||||
mail[botserver-mail]
|
||||
tasks[botserver-tasks]
|
||||
drive[botserver-drive]
|
||||
llm[botserver-llm]
|
||||
vectordb[botserver-vectordb]
|
||||
auto[botserver-auto]
|
||||
contacts[botserver-contacts]
|
||||
compliance[botserver-compliance]
|
||||
video[botserver-video]
|
||||
ui[botserver-ui]
|
||||
|
||||
botserver[botserver - Meta-crate]
|
||||
|
||||
botlib --> botstate
|
||||
botstate --> botcore
|
||||
botcore --> auth
|
||||
botcore --> chat
|
||||
botcore --> mail
|
||||
botcore --> tasks
|
||||
botcore --> drive
|
||||
botcore --> auto
|
||||
botcore --> contacts
|
||||
botcore --> compliance
|
||||
botcore --> video
|
||||
|
||||
llm --> botstate
|
||||
vectordb --> botstate
|
||||
vectordb --> llm
|
||||
|
||||
auth --> botstate
|
||||
chat --> botstate
|
||||
chat --> llm
|
||||
mail --> botstate
|
||||
tasks --> botstate
|
||||
drive --> botstate
|
||||
auto --> botstate
|
||||
contacts --> botstate
|
||||
compliance --> botstate
|
||||
video --> botstate
|
||||
|
||||
botserver --> botcore
|
||||
botserver --> auth
|
||||
botserver --> chat
|
||||
botserver --> mail
|
||||
botserver --> tasks
|
||||
botserver --> drive
|
||||
botserver --> llm
|
||||
botserver --> vectordb
|
||||
botserver --> auto
|
||||
botserver --> contacts
|
||||
botserver --> compliance
|
||||
botserver --> video
|
||||
botserver --> ui
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📁 File Structure After Migration
|
||||
|
||||
```
|
||||
gb/
|
||||
├── Cargo.toml (workspace)
|
||||
├── botlib/
|
||||
│ ├── Cargo.toml
|
||||
│ └── src/
|
||||
├── botstate/
|
||||
│ ├── Cargo.toml
|
||||
│ └── src/
|
||||
│ ├── lib.rs
|
||||
│ ├── state.rs
|
||||
│ ├── traits.rs
|
||||
│ └── config.rs
|
||||
├── botserver-core/
|
||||
│ ├── Cargo.toml
|
||||
│ └── src/
|
||||
│ ├── lib.rs
|
||||
│ ├── server.rs
|
||||
│ ├── middleware.rs
|
||||
│ └── health.rs
|
||||
├── botserver-auth/
|
||||
│ ├── Cargo.toml
|
||||
│ └── src/
|
||||
│ ├── lib.rs
|
||||
│ ├── jwt.rs
|
||||
│ ├── rbac.rs
|
||||
│ └── session.rs
|
||||
├── botserver-chat/
|
||||
│ ├── Cargo.toml
|
||||
│ └── src/
|
||||
│ ├── lib.rs
|
||||
│ ├── websocket.rs
|
||||
│ └── messages.rs
|
||||
├── botserver-mail/
|
||||
│ ├── Cargo.toml
|
||||
│ └── src/
|
||||
│ ├── lib.rs
|
||||
│ ├── imap.rs
|
||||
│ └── smtp.rs
|
||||
├── botserver-tasks/
|
||||
│ ├── Cargo.toml
|
||||
│ └── src/
|
||||
│ ├── lib.rs
|
||||
│ ├── scheduler.rs
|
||||
│ └── cron.rs
|
||||
├── botserver-drive/
|
||||
│ ├── Cargo.toml
|
||||
│ └── src/
|
||||
│ ├── lib.rs
|
||||
│ ├── s3.rs
|
||||
│ └── sync.rs
|
||||
├── botserver-llm/
|
||||
│ ├── Cargo.toml
|
||||
│ └── src/
|
||||
│ ├── lib.rs
|
||||
│ ├── provider.rs
|
||||
│ └── cache.rs
|
||||
├── botserver-vectordb/
|
||||
│ ├── Cargo.toml
|
||||
│ └── src/
|
||||
│ ├── lib.rs
|
||||
│ └── qdrant.rs
|
||||
├── botserver-auto/
|
||||
│ ├── Cargo.toml
|
||||
│ └── src/
|
||||
│ ├── lib.rs
|
||||
│ ├── rhai_engine.rs
|
||||
│ └── keywords.rs
|
||||
├── botserver-contacts/
|
||||
│ ├── Cargo.toml
|
||||
│ └── src/
|
||||
│ ├── lib.rs
|
||||
│ └── crm.rs
|
||||
├── botserver-compliance/
|
||||
│ ├── Cargo.toml
|
||||
│ └── src/
|
||||
│ ├── lib.rs
|
||||
│ └── audit.rs
|
||||
├── botserver-video/
|
||||
│ ├── Cargo.toml
|
||||
│ └── src/
|
||||
│ ├── lib.rs
|
||||
│ └── livekit.rs
|
||||
├── botserver-ui/
|
||||
│ ├── Cargo.toml
|
||||
│ └── src/
|
||||
│ ├── lib.rs
|
||||
│ └── tui.rs
|
||||
└── botserver/ (meta-crate)
|
||||
├── Cargo.toml
|
||||
└── src/
|
||||
├── main.rs
|
||||
└── lib.rs (re-exports)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Getting Started
|
||||
|
||||
### Step 1: Create botstate Crate
|
||||
```bash
|
||||
cd /home/rodriguez/src/gb
|
||||
mkdir -p botstate/src
|
||||
cat > botstate/Cargo.toml << 'EOF'
|
||||
[package]
|
||||
name = "botstate"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
botlib = { workspace = true }
|
||||
tokio = { workspace = true, features = ["full"] }
|
||||
redis = { workspace = true, features = ["tokio-comp"] }
|
||||
diesel = { workspace = true, features = ["postgres", "r2d2"] }
|
||||
chrono = { workspace = true }
|
||||
uuid = { workspace = true, features = ["v4"] }
|
||||
serde = { workspace = true, features = ["derive"] }
|
||||
async-trait = { workspace = true }
|
||||
EOF
|
||||
```
|
||||
|
||||
### Step 2: Update Workspace
|
||||
Edit `/home/rodriguez/src/gb/Cargo.toml`:
|
||||
```toml
|
||||
members = [
|
||||
"botapp",
|
||||
"botdevice",
|
||||
"botlib",
|
||||
"botserver",
|
||||
"bottest",
|
||||
"botui",
|
||||
"botstate", # NEW
|
||||
"botserver-core", # NEW
|
||||
"botserver-auth", # NEW
|
||||
"botserver-chat", # NEW
|
||||
# ... etc
|
||||
]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ✅ Success Criteria
|
||||
|
||||
1. ✅ **botstate** compiles independently
|
||||
2. ✅ **botserver-core** starts HTTP server without other services
|
||||
3. ✅ Each service can be built independently
|
||||
4. ✅ No circular dependencies between crates
|
||||
5. ✅ All tests pass
|
||||
6. ✅ Compile time reduced by 70% for individual services
|
||||
7. ✅ Memory usage during compilation reduced by 60%
|
||||
8. ✅ Backward compatibility maintained (existing code still works)
|
||||
|
||||
---
|
||||
|
||||
## 📝 Notes
|
||||
|
||||
- This plan prioritizes **incremental migration** - each step is reversible
|
||||
- Start with `botstate` and `botserver-core` as foundation
|
||||
- Test after each service extraction
|
||||
- Keep the meta-crate `botserver` for backward compatibility
|
||||
- Use feature flags to enable/disable services during transition
|
||||
|
||||
---
|
||||
|
||||
**Created**: 2026-04-18
|
||||
**Status**: Planning Phase
|
||||
**Next Step**: Create `botstate` crate with shared state types
|
||||
16
deploy.sh
Executable file
16
deploy.sh
Executable file
|
|
@ -0,0 +1,16 @@
|
|||
#!/bin/bash
|
||||
# Manual deploy script - run this on alm-ci container
|
||||
echo "1. Stop..."
|
||||
sudo incus exec system -- systemctl stop botserver || true
|
||||
sudo incus exec system -- pkill -x botserver || true
|
||||
sleep 1
|
||||
|
||||
echo "2. Copy..."
|
||||
sudo incus file push /opt/gbo/work/botserver/target/debug/botserver system:/opt/gbo/bin/botserver --mode=0755
|
||||
|
||||
echo "3. Start..."
|
||||
sudo incus exec system -- systemctl start botserver
|
||||
sleep 2
|
||||
|
||||
echo "4. Verify..."
|
||||
sudo incus exec system -- pgrep -x botserver && echo "✅ SUCCESS" || echo "❌ FAILED"
|
||||
296
prompts/integratedsuite.md
Normal file
296
prompts/integratedsuite.md
Normal file
|
|
@ -0,0 +1,296 @@
|
|||
# Integrated Suite — Conversational Interface Plan
|
||||
|
||||
> **Pattern:** Every suite app exposes its own `PROMPT.md` + internal tools.
|
||||
> The shared chat bar activates app-specific context when the user is inside that app.
|
||||
> WhatsApp campaigns is the first full example.
|
||||
a common chat window stay fixed right like pane colapsable, except for chat... all other ui must be controled by chat, via api/ pompt common mechanismo.
|
||||
---
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
User (WhatsApp / Suite chat bar)
|
||||
↓
|
||||
BotOrchestrator (core/bot/mod.rs)
|
||||
↓
|
||||
detect active app context
|
||||
↓
|
||||
load app PROMPT.md + app InternalTools
|
||||
↓
|
||||
LLM with tools → tool_executor.rs
|
||||
↓
|
||||
app data / actions
|
||||
```
|
||||
|
||||
### Key existing pieces
|
||||
| File | Role |
|
||||
|---|---|
|
||||
| `core/bot/mod.rs` | `get_session_tools()` + `ToolExecutor::execute_tool_call()` |
|
||||
| `tasks/PROMPT.md` | Pattern for app-level LLM prompt |
|
||||
| `marketing/whatsapp.rs` | WhatsApp campaign send/metrics |
|
||||
| `marketing/campaigns.rs` | Campaign CRUD |
|
||||
| `marketing/lists.rs` | Recipient lists |
|
||||
| `botui/ui/suite/campaigns/` | Campaigns UI |
|
||||
|
||||
---
|
||||
|
||||
## Standard: Every Suite App
|
||||
|
||||
### 1. `PROMPT.md` per app folder
|
||||
Location: `botserver/src/<app>/PROMPT.md`
|
||||
|
||||
```markdown
|
||||
# <App> — Internal Tools Guide
|
||||
|
||||
You are the <App> assistant. When the user is in <App>, you have access to:
|
||||
- tool: list_<entities>
|
||||
- tool: create_<entity>
|
||||
- tool: search_<entity>
|
||||
- tool: <app_specific_action>
|
||||
|
||||
Rules:
|
||||
- Always confirm destructive actions before executing
|
||||
- Show results as structured summaries, not raw JSON
|
||||
- If user uploads a file, parse it and confirm before acting
|
||||
```
|
||||
|
||||
### 2. `tools.rs` per app
|
||||
Location: `botserver/src/<app>/tools.rs`
|
||||
|
||||
Registers `Vec<Tool>` (LLM function-calling schema) + handler mapping.
|
||||
Loaded by `get_session_tools()` when session's active app = this app.
|
||||
|
||||
### 3. App context detection
|
||||
`core/bot/mod.rs` reads `session.active_app` (set by UI via `POST /api/session/context`).
|
||||
Loads `<app>/PROMPT.md` as system prompt prefix + `<app>/tools.rs` tools.
|
||||
|
||||
---
|
||||
|
||||
## WhatsApp Campaigns — Full Conversational Flow
|
||||
|
||||
### Meta Rules (enforced in tools)
|
||||
- Only approved Message Templates for marketing (non-session-initiated)
|
||||
- 24h session window for free-form after user replies
|
||||
- Media: image/video/document via Media Upload API before send
|
||||
- Opt-out: always honor STOP, add to suppression list immediately
|
||||
- Rate: respect per-phone-number rate limits (1000 msg/s business tier)
|
||||
- Template category: MARKETING requires explicit opt-in from recipient
|
||||
|
||||
### Conversation Flow (WhatsApp → campaign creation)
|
||||
|
||||
```
|
||||
User sends to bot number:
|
||||
"I want to send a campaign"
|
||||
↓
|
||||
Bot: "Great! Send me:
|
||||
1. Your contact list (.xlsx or .csv)
|
||||
2. The message text
|
||||
3. An image (optional)
|
||||
4. When to send (or 'now')"
|
||||
↓
|
||||
User uploads contacts.xlsx
|
||||
↓
|
||||
[tool: parse_contact_file]
|
||||
→ extract phone numbers, names
|
||||
→ validate E.164 format
|
||||
→ show preview: "Found 342 contacts. First 3: +55..."
|
||||
↓
|
||||
User sends message text
|
||||
↓
|
||||
[tool: check_template_compliance]
|
||||
→ check if free-form or needs approved template
|
||||
→ if template needed: list available approved templates
|
||||
→ suggest closest match
|
||||
↓
|
||||
User sends image (optional)
|
||||
↓
|
||||
[tool: upload_media]
|
||||
→ upload to Meta Media API
|
||||
→ return media_id
|
||||
↓
|
||||
Bot: "Ready to send to 342 contacts at 14:00 today.
|
||||
Preview: [image] Hello {name}, ...
|
||||
Estimated cost: $X
|
||||
Confirm? (yes/no)"
|
||||
↓
|
||||
User: "yes"
|
||||
↓
|
||||
[tool: create_and_schedule_campaign]
|
||||
→ create campaign record
|
||||
→ apply warmup limit if IP warming
|
||||
→ schedule via TaskScheduler
|
||||
```
|
||||
|
||||
### WhatsApp Campaign Tools (`marketing/whatsapp_tools.rs`)
|
||||
|
||||
```rust
|
||||
// Tool definitions for LLM function calling
|
||||
pub fn whatsapp_campaign_tools() -> Vec<Tool> {
|
||||
vec![
|
||||
Tool::new("parse_contact_file", "Parse uploaded xlsx/csv into contact list"),
|
||||
Tool::new("list_templates", "List approved WhatsApp message templates"),
|
||||
Tool::new("check_template_compliance", "Check if message needs approved template"),
|
||||
Tool::new("upload_media", "Upload image/video to Meta Media API"),
|
||||
Tool::new("preview_campaign", "Show campaign preview with cost estimate"),
|
||||
Tool::new("create_and_schedule_campaign", "Create campaign and schedule send"),
|
||||
Tool::new("get_campaign_status", "Get delivery/read metrics for a campaign"),
|
||||
Tool::new("pause_campaign", "Pause an in-progress campaign"),
|
||||
Tool::new("list_campaigns", "List recent campaigns with metrics"),
|
||||
Tool::new("add_to_suppression", "Add number to opt-out list"),
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### WhatsApp PROMPT.md (`marketing/WHATSAPP_PROMPT.md`)
|
||||
|
||||
```markdown
|
||||
# WhatsApp Campaign Assistant
|
||||
|
||||
You help users create and manage WhatsApp marketing campaigns.
|
||||
|
||||
## Meta Platform Rules (MANDATORY)
|
||||
- Marketing messages MUST use pre-approved templates outside 24h session window
|
||||
- Always check opt-in status before adding to campaign
|
||||
- Honor STOP/unsubscribe immediately via add_to_suppression tool
|
||||
- Never send more than warmup daily limit if IP is warming up
|
||||
- Image must be uploaded via upload_media before referencing in campaign
|
||||
|
||||
## Conversation Style
|
||||
- Guide step by step: contacts → message → media → schedule → confirm
|
||||
- Show cost estimate before confirming
|
||||
- After send: proactively share open/read rates when available
|
||||
|
||||
## File Handling
|
||||
- .xlsx/.csv → use parse_contact_file tool
|
||||
- Images → use upload_media tool
|
||||
- Always confirm parsed data before proceeding
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Integrated Suite Chat Bar — Standard
|
||||
|
||||
### How it works
|
||||
1. User opens any suite app (CRM, Campaigns, Drive, etc.)
|
||||
2. Chat bar at bottom activates with app context
|
||||
3. `POST /api/session/context { app: "campaigns" }` sets `session.active_app`
|
||||
4. BotOrchestrator loads `campaigns/PROMPT.md` + `campaigns/tools.rs`
|
||||
5. User can ask natural language questions or trigger actions
|
||||
|
||||
### Examples per app
|
||||
|
||||
| App | Example query | Tool activated |
|
||||
|---|---|---|
|
||||
| **Campaigns** | "How did last week's campaign perform?" | `get_campaign_metrics` |
|
||||
| **CRM** | "Show deals closing this month" | `list_deals` with filter |
|
||||
| **Drive** | "Find the Q1 report" | `search_files` |
|
||||
| **Tasks** | "Create a task to follow up with Acme" | `create_task` |
|
||||
| **People** | "Who hasn't been contacted in 30 days?" | `list_contacts` with filter |
|
||||
| **Mail** | "Summarize unread emails from clients" | `list_emails` + LLM summary |
|
||||
| **Sheet** | "What's the total revenue in column D?" | `query_sheet` |
|
||||
| **Learn** | "What does our refund policy say?" | `search_kb` |
|
||||
|
||||
---
|
||||
|
||||
## Implementation Plan
|
||||
|
||||
### Phase 1 — Infrastructure (1 sprint)
|
||||
- [ ] `core/bot/mod.rs` — read `session.active_app`, load app PROMPT + tools
|
||||
- [ ] `core/tool_context.rs` — app tool registry: `register_app_tools(app_name) -> Vec<Tool>`
|
||||
- [ ] `POST /api/session/context` — set active app from UI
|
||||
- [ ] Suite chat bar UI component (`botui/ui/suite/partials/chatbar.html`)
|
||||
|
||||
### Phase 2 — WhatsApp Campaigns (1 sprint)
|
||||
- [ ] `marketing/whatsapp_tools.rs` — 10 tools above
|
||||
- [ ] `marketing/WHATSAPP_PROMPT.md`
|
||||
- [ ] `marketing/file_parser.rs` — xlsx/csv → contact list
|
||||
- [ ] Meta warmup enforcement in send path
|
||||
- [ ] Conversational campaign creation flow (state machine in session)
|
||||
|
||||
### Phase 3 — App-by-app rollout (1 app/sprint)
|
||||
Priority order based on value:
|
||||
1. CRM (deals, contacts, pipeline queries)
|
||||
2. Campaigns (email + WhatsApp)
|
||||
3. Tasks (create, assign, status)
|
||||
4. Drive (search, summarize docs)
|
||||
5. Mail (summarize, draft reply)
|
||||
6. People (segment, find contacts)
|
||||
7. Sheet (query, calculate)
|
||||
8. Learn (KB search)
|
||||
|
||||
### Phase 4 — Cross-app intelligence
|
||||
- [ ] Global search across all apps via single query
|
||||
- [ ] "What happened today?" — aggregates activity across CRM + Mail + Tasks
|
||||
- [ ] Proactive suggestions: "You have 3 deals closing this week and no follow-up tasks"
|
||||
|
||||
---
|
||||
|
||||
## File Structure to Create
|
||||
|
||||
```
|
||||
botserver/src/
|
||||
├── marketing/
|
||||
│ ├── whatsapp_tools.rs ← NEW: LLM tool definitions + handlers
|
||||
│ ├── WHATSAPP_PROMPT.md ← NEW: WhatsApp assistant system prompt
|
||||
│ ├── file_parser.rs ← NEW: xlsx/csv → contacts
|
||||
│ └── warmup.rs ← NEW: (from campaigns.md plan)
|
||||
├── core/
|
||||
│ ├── tool_registry.rs ← NEW: app → tools mapping
|
||||
│ └── bot/
|
||||
│ └── app_context.rs ← NEW: load app prompt + tools per session
|
||||
├── crm/
|
||||
│ ├── tools.rs ← NEW
|
||||
│ └── PROMPT.md ← NEW
|
||||
├── tasks/
|
||||
│ └── tools.rs ← NEW (PROMPT.md exists)
|
||||
└── <each app>/
|
||||
├── tools.rs ← NEW per app
|
||||
└── PROMPT.md ← NEW per app
|
||||
|
||||
botui/ui/suite/
|
||||
└── partials/
|
||||
└── chatbar.html ← NEW: shared chat bar component
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Chat Bar UI (`partials/chatbar.html`)
|
||||
|
||||
```html
|
||||
<div id="suite-chatbar" class="chatbar">
|
||||
<div id="chatbar-messages" hx-ext="ws" ws-connect="/ws/suite-chat"></div>
|
||||
<form ws-send>
|
||||
<input type="hidden" name="app_context" value="{{ active_app }}">
|
||||
<input type="file" id="chatbar-file" name="file" accept=".xlsx,.csv,.png,.jpg,.pdf" style="display:none">
|
||||
<button type="button" onclick="document.getElementById('chatbar-file').click()">📎</button>
|
||||
<input type="text" name="message" placeholder="Ask anything about {{ active_app }}...">
|
||||
<button type="submit">→</button>
|
||||
</form>
|
||||
</div>
|
||||
```
|
||||
|
||||
File uploads go to `POST /api/suite/upload` → stored in Drive → media_id passed to tool.
|
||||
|
||||
---
|
||||
|
||||
## Compilation & Validation Log
|
||||
|
||||
**Last Validated:** 2026-04-17
|
||||
|
||||
**Status:** ✅ Design Document - No Code to Compile
|
||||
|
||||
**Validation Checklist:**
|
||||
- [x] Architecture diagram is clear
|
||||
- [x] App pattern is defined
|
||||
- [x] WhatsApp campaign flow is documented
|
||||
- [x] Tool definitions are complete
|
||||
- [x] HTML structure is valid
|
||||
- [x] Rust code examples are syntactically correct
|
||||
- [x] Implementation phases are planned
|
||||
- [x] File structure is organized
|
||||
|
||||
**Notes:**
|
||||
- This is a design document for integrated suite conversational interface
|
||||
- No compilation required - it's planning documentation
|
||||
- Ready for implementation when developer is available
|
||||
- References existing code in botserver/src/marketing/ and botserver/src/core/bot/
|
||||
10
reset.sh
Executable file
10
reset.sh
Executable file
|
|
@ -0,0 +1,10 @@
|
|||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
echo "Cleaning up..."
|
||||
rm -rf botserver-stack/ ./work/ .env
|
||||
|
||||
echo "Starting services..."
|
||||
./restart.sh
|
||||
|
||||
echo "Reset complete!"
|
||||
32
restart.ps1
Normal file
32
restart.ps1
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
$ErrorActionPreference = "Continue"
|
||||
|
||||
Write-Host "Stopping..."
|
||||
Stop-Process -Name "botserver" -Force -ErrorAction SilentlyContinue
|
||||
Stop-Process -Name "botui" -Force -ErrorAction SilentlyContinue
|
||||
Stop-Process -Name "rustc" -Force -ErrorAction SilentlyContinue
|
||||
|
||||
Write-Host "Cleaning..."
|
||||
Remove-Item -Path "botserver.log", "botui.log" -Force -ErrorAction SilentlyContinue
|
||||
|
||||
Write-Host "Building..."
|
||||
cargo build -p botserver
|
||||
if ($LASTEXITCODE -ne 0) { Write-Host "Failed to build botserver"; exit 1 }
|
||||
|
||||
cargo build -p botui
|
||||
if ($LASTEXITCODE -ne 0) { Write-Host "Failed to build botui"; exit 1 }
|
||||
|
||||
Write-Host "Starting botserver..."
|
||||
$env:PORT = "8080"
|
||||
$env:RUST_LOG = "debug"
|
||||
$env:PATH += ";C:\pgsql\pgsql\bin;C:\pgsql\pgsql\lib"
|
||||
$botserverProcess = Start-Process -PassThru -NoNewWindow -FilePath ".\target\debug\botserver.exe" -ArgumentList "--noconsole" -RedirectStandardOutput "botserver.log" -RedirectStandardError "botserver.log"
|
||||
Write-Host " PID: $($botserverProcess.Id)"
|
||||
|
||||
Write-Host "Starting botui..."
|
||||
$env:BOTSERVER_URL = "http://localhost:8080"
|
||||
$env:PORT = "3000"
|
||||
$botuiProcess = Start-Process -PassThru -NoNewWindow -FilePath ".\target\debug\botui.exe" -RedirectStandardOutput "botui.log" -RedirectStandardError "botui.log"
|
||||
Write-Host " PID: $($botuiProcess.Id)"
|
||||
|
||||
Write-Host "Done. Logs are being written to botserver.log and botui.log"
|
||||
Write-Host "To view logs, you can use: Get-Content botserver.log -Wait"
|
||||
49
restart.sh
Executable file
49
restart.sh
Executable file
|
|
@ -0,0 +1,49 @@
|
|||
#!/bin/bash
|
||||
|
||||
echo "=== Fast Restart: botserver + botmodels only ==="
|
||||
|
||||
# Kill only the app services, keep infra running
|
||||
pkill -f "botserver --noconsole" || true
|
||||
pkill -f "botmodels" || true
|
||||
|
||||
# Clean logs
|
||||
rm -f botserver.log botmodels.log
|
||||
|
||||
# Build only botserver (botui likely already built)
|
||||
cargo build -p botserver
|
||||
|
||||
# Start botmodels
|
||||
cd botmodels
|
||||
source venv/bin/activate
|
||||
uvicorn src.main:app --host 0.0.0.0 --port 8085 > ../botmodels.log 2>&1 &
|
||||
echo " botmodels PID: $!"
|
||||
cd ..
|
||||
|
||||
# Wait for botmodels
|
||||
for i in $(seq 1 20); do
|
||||
if curl -s http://localhost:8085/api/health > /dev/null 2>&1; then
|
||||
echo " botmodels ready"
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
|
||||
# Start botserver (keep botui running if already up)
|
||||
if ! pgrep -f "botui" > /dev/null; then
|
||||
echo "Starting botui..."
|
||||
cargo build -p botui
|
||||
cd botui
|
||||
BOTSERVER_URL="http://localhost:8080" ./target/debug/botui > ../botui.log 2>&1 &
|
||||
echo " botui PID: $!"
|
||||
cd ..
|
||||
fi
|
||||
|
||||
# Start botserver
|
||||
BOTMODELS_HOST="http://localhost:8085" BOTMODELS_API_KEY="starter" RUST_LOG=info ./target/debug/botserver --noconsole > botserver.log 2>&1 &
|
||||
echo " botserver PID: $!"
|
||||
|
||||
# Quick health check
|
||||
sleep 2
|
||||
curl -s http://localhost:8080/health > /dev/null 2>&1 && echo "✅ botserver ready" || echo "❌ botserver failed"
|
||||
|
||||
echo "Done. botserver $(pgrep -f 'botserver --noconsole') botui $(pgrep -f botui) botmodels $(pgrep -f botmodels)"
|
||||
Loading…
Add table
Reference in a new issue