BxDolAiAgentTools.php 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. <?php defined('BX_DOL') or die('hack attempt');
  2. /**
  3. * Copyright (c) UNA, Inc - https://una.io
  4. * MIT License - https://opensource.org/licenses/MIT
  5. *
  6. * Tools attached in code. They are not stored on the agent and are not offered
  7. * in the Studio tool picker, the tools grid, or agent_create.
  8. * mysql_schema and mysql_select are mandatory on una_operator and stay visible.
  9. * mysql_write_safe and mysql_undo do not.
  10. *
  11. * @defgroup UnaCore UNA Core
  12. * @{
  13. */
  14. class BxDolAiAgentTools
  15. {
  16. /** Every agent. */
  17. public const ALWAYS = ['chat_buttons', 'chat_title'];
  18. /** una_operator, in addition to ALWAYS. Hidden from the picker. mysql_write is not included. */
  19. public const OPERATOR = [
  20. 'agent_create',
  21. 'mockup_upsert',
  22. 'mysql_write_safe',
  23. 'mysql_undo',
  24. ];
  25. /** una_operator, in addition to ALWAYS and OPERATOR. Visible, so other agents can keep them. */
  26. public const OPERATOR_READ = ['mysql_schema', 'mysql_select'];
  27. public static function typesFor(array $aAgent): array
  28. {
  29. $a = self::ALWAYS;
  30. if (($aAgent['name'] ?? '') === 'una_operator')
  31. $a = array_merge($a, self::OPERATOR, self::OPERATOR_READ);
  32. return $a;
  33. }
  34. public static function hiddenTypes(): array
  35. {
  36. return array_values(array_unique(array_merge(self::ALWAYS, self::OPERATOR)));
  37. }
  38. /**
  39. * Studio tools grid source, with locked types removed.
  40. */
  41. public static function excludeHiddenFromSource(string $sSource): string
  42. {
  43. if (stripos($sSource, ' WHERE ') === false)
  44. $sSource .= ' WHERE 1 ';
  45. return $sSource . ' AND `type` NOT IN (' . BxDolDb::getInstance()->implode_escape(self::hiddenTypes()) . ')';
  46. }
  47. /**
  48. * One active row per type that this agent must have, lowest id.
  49. *
  50. * @return int[]
  51. */
  52. public static function idsFor(array $aAgent): array
  53. {
  54. $aTypes = self::typesFor($aAgent);
  55. if (!$aTypes)
  56. return [];
  57. $aIds = [];
  58. $aSeen = [];
  59. foreach ((new BxDolAiQuery())->getActiveToolsByTypes($aTypes) as $aRow) {
  60. $sType = (string)$aRow['type'];
  61. if (isset($aSeen[$sType]))
  62. continue;
  63. $aSeen[$sType] = true;
  64. $aIds[] = (int)$aRow['id'];
  65. }
  66. return $aIds;
  67. }
  68. /**
  69. * Every row of a locked type, including inactive copies, so a stored id cannot grant one.
  70. *
  71. * @return int[]
  72. */
  73. public static function hiddenIds(): array
  74. {
  75. $aTypes = self::hiddenTypes();
  76. if (!$aTypes)
  77. return [];
  78. return (new BxDolAiQuery())->getToolIdsByTypes($aTypes);
  79. }
  80. /**
  81. * Stored ids minus locked ones, plus the ids this agent always has.
  82. *
  83. * @return int[]
  84. */
  85. public static function resolveIds(array $aAgent): array
  86. {
  87. $aIds = [];
  88. if (!empty($aAgent['tools'])) {
  89. foreach (explode(',', (string)$aAgent['tools']) as $sToolId) {
  90. $iToolId = (int)trim($sToolId);
  91. if ($iToolId > 0)
  92. $aIds[$iToolId] = $iToolId;
  93. }
  94. }
  95. foreach (self::hiddenIds() as $iHidden)
  96. unset($aIds[$iHidden]);
  97. foreach (self::idsFor($aAgent) as $iId)
  98. $aIds[$iId] = $iId;
  99. return array_values($aIds);
  100. }
  101. public static function stripCsv(string $sTools): string
  102. {
  103. $sTools = trim($sTools);
  104. if ($sTools === '')
  105. return '';
  106. $aHidden = array_flip(self::hiddenIds());
  107. $aKeep = [];
  108. foreach (explode(',', $sTools) as $sId) {
  109. $iId = (int)trim($sId);
  110. if ($iId <= 0 || isset($aHidden[$iId]))
  111. continue;
  112. $aKeep[$iId] = $iId;
  113. }
  114. return implode(',', $aKeep);
  115. }
  116. }
  117. /** @} */