ai_agents_test-1.0.0-alpha1/src/Form/InteractiveAgentTestForm.php
src/Form/InteractiveAgentTestForm.php
<?php
declare(strict_types=1);
namespace Drupal\ai_agents_test\Form;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\TempStore\PrivateTempStoreFactory;
use Drupal\ai\Service\FunctionCalling\FunctionCallPluginManager;
use Drupal\ai_agents_test\AgentTestInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Yaml\Yaml;
/**
* Form controller for the agent test entity edit forms.
*/
final class InteractiveAgentTestForm extends FormBase {
/**
* Constructs a new InteractiveAgentTestForm object.
*
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager
* The entity type manager service.
* @param \Drupal\ai\Service\FunctionCalling\FunctionCallPluginManager $functionCallPluginManager
* The function call plugin manager service.
* @param \Drupal\Core\TempStore\PrivateTempStoreFactory $tempStore
* The private temp store factory service.
*/
public function __construct(
protected EntityTypeManagerInterface $entityTypeManager,
protected FunctionCallPluginManager $functionCallPluginManager,
protected PrivateTempStoreFactory $tempStore,
) {
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container): static {
return new static(
$container->get('entity_type.manager'),
$container->get('plugin.manager.ai.function_calls'),
$container->get('tempstore.private'),
);
}
/**
* {@inheritdoc}
*/
public function getFormId(): string {
return 'ai_agents_test_form';
}
/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state, ?AgentTestInterface $ai_agents_test = NULL): array {
$form = [];
// Check the query string for the agent id.
$agent_id = $this->getRequest()->query->get('agent_id');
if ($agent_id) {
$form_state->set('ai_agent', $agent_id);
}
$form['entity_id'] = [
'#type' => 'hidden',
'#value' => $ai_agents_test ? $ai_agents_test->id() : NULL,
];
// This should only load on the first page load, not on ajax or submit.
if (!$form_state->isRebuilding()) {
// Check if some imported rules are in the private temp store.
if (!$ai_agents_test) {
$this->loadFromTempStore($form, $form_state);
}
else {
$this->loadFromEntity($form, $form_state, $ai_agents_test);
}
}
$form['#prefix'] = '<div id="rules-wrapper">';
$form['#suffix'] = '</div>';
$form['meta'] = [
'#type' => 'details',
'#title' => $this->t('Meta'),
'#open' => TRUE,
];
$form['meta']['label'] = [
'#type' => 'textfield',
'#title' => $this->t('Title'),
'#description' => $this->t('The title of the agent test.'),
'#required' => TRUE,
'#default_value' => $form_state->getValue('label') ?? $form_state->get('label'),
];
$form['meta']['description'] = [
'#type' => 'textarea',
'#title' => $this->t('Description'),
'#description' => $this->t('Describe what the test does, what you are hoping to test and what expected results you have.'),
'#required' => TRUE,
'#attributes' => [
'rows' => 2,
],
'#default_value' => $form_state->getValue('description') ?? $form_state->get('description'),
];
$form['meta']['triggering_instructions'] = [
'#type' => 'textarea',
'#title' => $this->t('Triggering Instructions'),
'#description' => $this->t('The instructions that trigger the agent tests. This is only used for getting an information overview of what the test does and does not affect the test.'),
'#required' => TRUE,
'#attributes' => [
'rows' => 2,
],
'#default_value' => $form_state->getValue('triggering_instructions') ?? $form_state->get('triggering_instructions'),
];
$form['usage'] = [
'#type' => 'details',
'#title' => $this->t('Usage'),
'#open' => TRUE,
];
// Get all the ai agent config entities.
$agent_storage = $this->entityTypeManager->getStorage('ai_agent');
$agents = $agent_storage->loadMultiple();
// Order by label.
$agents = array_map(
static fn($agent) => $agent->label(),
$agents,
);
asort($agents);
$form['usage']['ai_agent'] = [
'#type' => 'select',
'#title' => $this->t('Agent'),
'#description' => $this->t('The agent to test.'),
'#options' => $agents,
'#required' => TRUE,
// This is disabled if rules have been added.
'#default_value' => $form_state->getValue('ai_agent') ?? $form_state->get('ai_agent'),
];
if ($form_state->getValue('advanced_history')) {
// Get all the chat history from the form state.
$chat_history = $form_state->get('chat_history');
if (!$chat_history) {
$chat_history[] = [
'role' => 'user',
'text' => '',
];
$form_state->set('chat_history', $chat_history);
}
$form['usage']['chat_history'] = [
'#type' => 'details',
'#title' => $this->t('Chat History'),
'#open' => TRUE,
'#tree' => TRUE,
];
foreach ($chat_history as $key => $history) {
$form['usage']['chat_history']['chat_history_' . $key] = [
'#type' => 'details',
'#title' => $this->t('Chat History %number', ['%number' => $key + 1]),
'#open' => TRUE,
];
$form['usage']['chat_history']['chat_history_' . $key]['role'] = [
'#type' => 'select',
'#options' => [
'user' => $this->t('User'),
'assistant' => $this->t('Assistant'),
],
'#title' => $this->t('Role'),
'#description' => $this->t('The role of the message.'),
'#required' => TRUE,
'#default_value' => $history['role'],
];
$form['usage']['chat_history']['chat_history_' . $key]['text'] = [
'#type' => 'textarea',
'#title' => $this->t('Text'),
'#description' => $this->t('The text of the message.'),
'#default_value' => $history['text'],
'#attributes' => [
'rows' => 2,
],
];
}
// Add a button to add a new chat history.
$form['usage']['chat_history']['add_chat_history'] = [
'#type' => 'submit',
'#value' => $this->t('Add Chat History'),
'#submit' => [[static::class, 'addChatHistorySubmit']],
'#ajax' => [
'callback' => [static::class, 'addChatHistoryCallback'],
'wrapper' => 'rules-wrapper',
],
'#limit_validation_errors' => [['ai_agent'], ['rules']],
];
}
else {
$messages = NULL;
if (!empty($form_state->getValue('messages'))) {
$messages = $form_state->getValue('messages')[0]['content'];
}
elseif ($form_state->get('messages')) {
$messages = $form_state->get('messages')[0]['content'];
}
$form['usage']['instructions'] = [
'#type' => 'textarea',
'#title' => $this->t('Instructions'),
'#description' => $this->t('The instructions for the agent. This is the prompt that will be sent to the agent to try to solve.'),
'#required' => TRUE,
'#attributes' => [
'rows' => 3,
],
'#default_value' => $messages,
];
}
$form['usage']['advanced_history'] = [
'#type' => 'checkbox',
'#title' => $this->t('History'),
'#description' => $this->t('Use chat history for the instructions.'),
'#default_value' => $form_state->get('advanced_history') ?? FALSE,
'#ajax' => [
'callback' => [static::class, 'advancedHistoryCallback'],
'wrapper' => 'rules-wrapper',
],
];
$form['usage']['config_reset'] = [
'#type' => 'checkbox',
'#title' => $this->t('Reset Config'),
'#description' => $this->t('Reset the config after running the test. Only add this if you need to reset the config, since it can be slow.'),
'#default_value' => $form_state->get('config_reset') ?? FALSE,
];
// Get all the rules from the form state.
$rules = $form_state->get('rules');
$form['rules'] = [
'#type' => 'details',
'#title' => $this->t('Rules'),
'#open' => TRUE,
'#tree' => TRUE,
// Only show if an agent has been selected.
'#states' => [
'visible' => [
':input[name="agent"]' => ['!value' => ''],
],
],
];
if ($rules) {
foreach ($rules as $rule) {
$this->createRuleElement($form, $form_state, $rule);
}
}
// Add a button to add a new rule.
$form['rules']['add_rule'] = [
'#type' => 'submit',
'#value' => $this->t('Add Rule'),
'#submit' => [[static::class, 'addRuleSubmit']],
'#ajax' => [
'callback' => [static::class, 'addRuleCallback'],
'wrapper' => 'rules-wrapper',
],
'#limit_validation_errors' => [['ai_agent']],
];
$form['rules']['response_rule'] = [
'#type' => 'textarea',
'#title' => $this->t('Agent Response LLM Test'),
'#description' => $this->t('If filled in, this prompt will be tested against the agents response.'),
'#attributes' => [
'rows' => 3,
],
'#default_value' => $form_state->getValue('response_rule') ?? $form_state->get('response_rule') ?? '',
];
// Advanced section.
$form['advanced'] = [
'#type' => 'details',
'#title' => $this->t('Advanced'),
'#open' => FALSE,
];
// YAML for replacement tokens.
$form['advanced']['tokens'] = [
'#type' => 'textarea',
'#title' => $this->t('Tokens YAML'),
'#description' => $this->t('The tokens to inject into all the agents being used in this test, in YAML format.'),
'#attributes' => [
'rows' => 10,
'style' => 'font-family: monospace;',
'placeholder' => "node:\n id: 123\n title: 'Alice'",
],
'#default_value' => $form_state->getValue('tokens') ?? $form_state->get('tokens') ?? '',
];
// Save the agent.
$form['action'] = [
'#type' => 'actions',
];
$form['action']['submit'] = [
'#type' => 'submit',
'#value' => $this->t('Save Test'),
];
return $form;
}
/**
* Create a rule form element.
*
* @param array $form
* The form array.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The form state.
* @param string $rule
* The rule to test.
*/
protected function createRuleElement(array &$form, FormStateInterface $form_state, string $rule) {
// Get the config of the chosen agent.
$agent = $form_state->getValue('ai_agent') ?? $form_state->get('ai_agent');
if (!$agent) {
return;
}
// Get the agent config entity.
$agent_storage = $this->entityTypeManager->getStorage('ai_agent');
/** @var \Drupal\ai_agents\Entity\AgentInterface $agent_config */
$agent_config = $agent_storage->load($agent);
if (!$agent_config) {
return;
}
// Get the tools for the agent.
$tools = $agent_config->get('tools');
if (!$tools) {
return;
}
// If the rule is the "add_rule" button, then we need to create a new rule.
if ($rule === 'add_rule') {
return;
}
// Load all the tools.
$tool_options = [];
foreach ($tools as $tool => $enabled) {
$tools_definition = $this->functionCallPluginManager->getDefinition($tool);
if ($tools_definition) {
$tool_options[$tool] = $tools_definition['name'];
}
}
$form['rules'][$rule] = [
'#type' => 'details',
'#title' => $rule,
'#open' => TRUE,
];
$form['rules'][$rule]['tool'] = [
'#type' => 'select',
'#title' => $this->t('Rules for the tool'),
'#description' => $this->t('Pick a tool that you want to set a rule for.'),
'#options' => $tool_options,
'#required' => TRUE,
'#empty_option' => $this->t('Select a tool'),
'#default_value' => $form_state->getValue('rules')[$rule]['tool'] ?? '',
// If you pick, then the tool, show the tool options.
'#ajax' => [
'callback' => [static::class, 'advancedHistoryCallback'],
'wrapper' => 'rules-wrapper',
],
];
$values = $form_state->getUserInput()['rules'][$rule] ?? $form_state->getValue('rules')[$rule] ?? [];
// Add extra parameter options.
if (!empty($values['tool'])) {
// Create an instance of the tool.
$tool_instance = $this->functionCallPluginManager->createInstance($values['tool']);
$tools_definition = $this->functionCallPluginManager->getDefinition($values['tool']);
$form['rules'][$rule]['label'] = [
'#type' => 'textfield',
'#title' => $this->t('Label'),
'#description' => $this->t('The label for the rule.'),
'#required' => TRUE,
'#default_value' => $values['label'] ?? '',
];
$form['rules'][$rule]['tool_rules'] = [
'#type' => 'select',
'#title' => $this->t('Tool Rules'),
'#description' => $this->t('The rules for the tool %name to pass the test.', ['%name' => $tools_definition['name']]),
'#required' => TRUE,
'#empty_option' => $this->t('Select a rule'),
'#default_value' => $values['tool_rules'] ?? '',
'#options' => [
'should_be_run' => $this->t('Should be run'),
'should_not_be_run' => $this->t('Should not be run'),
],
];
$form['rules'][$rule]['tool_order'] = [
'#type' => 'select',
'#title' => $this->t('Tool Order'),
'#description' => $this->t('The order of when the tool %name should be run to pass the test.', ['%name' => $tools_definition['name']]),
'#required' => TRUE,
'#default_value' => $values['tool_order'] ?? 'any',
'#options' => [
'any' => $this->t('Any time'),
'one_of' => $this->t('One of the loops'),
'sometime_after_tool' => $this->t('Sometime after the tool'),
'sometime_before_tool' => $this->t('Sometime before the tool'),
'directly_after_tool' => $this->t('Directly after the tool'),
'directly_before_tool' => $this->t('Directly before the tool'),
],
// Only when it should be run.
'#states' => [
'visible' => [
':input[name="rules[' . $rule . '][tool_rules]"]' => ['value' => 'should_be_run'],
],
],
];
$form['rules'][$rule]['tool_loop_order'] = [
'#type' => 'textfield',
'#title' => $this->t('Tool Loop Order'),
'#description' => $this->t('The order of when the tool %name should be run to pass the test. Comma separated if its many.', ['%name' => $tools_definition['name']]),
'#default_value' => $values['tool_loop_order'] ?? '',
'#states' => [
'visible' => [
':input[name="rules[' . $rule . '][tool_order]"]' => ['value' => 'one_of'],
],
],
];
$form['rules'][$rule]['tool_other_tool_order'] = [
'#type' => 'select',
'#title' => $this->t('Dependent Tool Order'),
'#description' => $this->t('The tool for the Tool Order set above.', ['%name' => $tools_definition['name']]),
'#options' => $tool_options,
'#default_value' => $values['tool_other_tool_order'] ?? '',
'#states' => [
'visible' => [
':input[name="rules[' . $rule . '][tool_order]"]' => [
['value' => 'sometime_after_tool'],
'or',
['value' => 'sometime_before_tool'],
'or',
['value' => 'directly_after_tool'],
'or',
['value' => 'directly_before_tool'],
],
],
],
];
// Get all the context definitions.
$context_definitions = $tool_instance->getContextDefinitions();
// Set up options for each of the context definitions.
foreach ($context_definitions as $key => $context_definition) {
$form['rules'][$rule]['parameters'][$key] = [
'#type' => 'details',
'#title' => $this->t('Parameter %key', ['%key' => $context_definition->getLabel()]),
'#open' => FALSE,
'#states' => [
'visible' => [
':input[name="rules[' . $rule . '][tool_rules]"]' => ['value' => 'should_be_run'],
],
],
];
$form['rules'][$rule]['parameters'][$key]['type_of_check'] = [
'#type' => 'select',
'#title' => $this->t('Rule'),
'#description' => $this->t('The parameter rule for %title. For the <em>one of</em> rules, give a comma separated list.', ['%title' => $context_definition->getLabel()]),
'#required' => TRUE,
'#default_value' => $values['parameters'][$key]['type_of_check'] ?? 'empty',
'#options' => [
'empty' => $this->t('No rules'),
'isset' => $this->t('Is set'),
'not_set' => $this->t('Is not set'),
'equals' => $this->t('Is exactly'),
'not_equals' => $this->t('Is exactly not'),
'one_of' => $this->t('Is one of'),
'not_one_of' => $this->t('Is not one of'),
'greater_than' => $this->t('Is greater than'),
'less_than' => $this->t('Is less than'),
'llm' => $this->t('Is verified by LLM'),
],
];
$form['rules'][$rule]['parameters'][$key]['value'] = [
'#type' => 'textarea',
'#title' => $this->t('Value'),
'#description' => $this->t('The value to check for %title. If its <em>one of</em> it should be a comma separated list.', ['%title' => $context_definition->getLabel()]),
'#default_value' => $values['parameters'][$key]['value'] ?? '',
'#rows' => 2,
'#states' => [
'visible' => [
':input[name="rules[' . $rule . '][' . $key . '][type_of_check]"]' => [
['value' => 'equals'],
'or',
['value' => 'not_equals'],
'or',
['value' => 'greater_than'],
'or',
['value' => 'less_than'],
'or',
['value' => 'one_of'],
'or',
['value' => 'not_one_of'],
'or',
['value' => 'llm'],
],
],
],
];
}
}
$form['rules'][$rule]['remove'] = [
'#type' => 'submit',
'#value' => $this->t('Remove'),
'#name' => 'remove_' . $rule,
'#submit' => [[static::class, 'removeRuleSubmit']],
'#ajax' => [
'callback' => [static::class, 'removeRuleCallback'],
'wrapper' => 'rules-wrapper',
],
'#attributes' => [
'class' => ['button'],
],
'#limit_validation_errors' => [],
];
}
/**
* {@inheritDoc}
*/
public function validateForm(array &$form, FormStateInterface $form_state): void {
// Validate the YAML for the tokens.
$tokens_yaml = $form_state->getValue('tokens');
if (!empty($tokens_yaml)) {
try {
Yaml::parse($tokens_yaml);
}
catch (\Exception $e) {
$form_state->setErrorByName('tokens', $this->t('The tokens YAML is not valid: %message', ['%message' => $e->getMessage()]));
}
}
}
/**
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state): void {
// Save the entity.
$storage = $this->entityTypeManager->getStorage('ai_agents_test');
$entity_id = $form_state->getValue('entity_id');
if ($entity_id) {
/** @var \Drupal\ai_agents_test\Entity\AgentTestInterface $agent_test */
$agent_test = $storage->load($entity_id);
}
else {
/** @var \Drupal\ai_agents_test\Entity\AgentTestInterface $agent_test */
$agent_test = $storage->create([]);
$agent_test->set('created', time());
$agent_test->set('uid', $this->currentUser()->id());
}
// Set the values for the entity.
$agent_test->set('label', $form_state->getValue('label'));
$agent_test->set('description', $form_state->getValue('description'));
$agent_test->set('ai_agent', $form_state->getValue('ai_agent'));
$agent_test->set('rules', Yaml::dump($form_state->getValue('rules'), 10, 2));
$agent_test->set('config_reset', $form_state->getValue('config_reset'));
$agent_test->set('triggering_instructions', $form_state->getValue('triggering_instructions'));
if ($form_state->getValue('advanced_history')) {
$chat_history = [];
foreach ($form_state->getValue('chat_history') as $history) {
if (is_array($history) && !empty($history['text'])) {
$chat_history[] = [
'role' => $history['role'],
'content' => $history['text'],
];
}
}
}
else {
$chat_history = [
[
'role' => 'user',
'content' => $form_state->getValue('instructions'),
],
];
}
$agent_test->set('messages', Yaml::dump($chat_history, 10, 2));
$agent_test->set('changed', time());
$agent_test->set('tokens', $form_state->getValue('tokens'));
$agent_test->save();
// Remove the import from the private temp store.
$this->tempStore->get('ai_agents_test')->delete('import');
// Redirect to the listing pages with the agent_id as a query string.
$form_state->setRedirect('entity.ai_agents_test.collection', [
'agent_id' => $form_state->getValue('ai_agent'),
]);
}
/**
* Ajax callback to show/hide the rules.
*/
/**
* The submit handler for the add rule button.
*/
public static function addRuleSubmit(array &$form, FormStateInterface $form_state): void {
$rules = $form_state->get('rules') ?? [];
// Find the highest rule number.
$max_number = 0;
foreach ($rules as $rule) {
if (preg_match('/^rule_(\d+)$/', $rule, $matches)) {
$max_number = max($max_number, (int) $matches[1]);
}
}
// Add a new rule with the next available number.
$rules[] = 'rule_' . ($max_number + 1);
$form_state->set('rules', $rules);
$agent = $form_state->getValue('ai_agent');
$form_state->set('ai_agent', $agent);
// Preserve the advanced_history setting.
$advanced_history = $form_state->getValue('advanced_history') ??
$form_state->getUserInput()['advanced_history'] ??
$form_state->get('advanced_history') ??
FALSE;
$form_state->setValue('advanced_history', $advanced_history);
$form_state->set('advanced_history', $advanced_history);
$form_state->setRebuild(TRUE);
}
/**
* The submit handler for the remove rule button.
*/
public static function removeRuleSubmit(array &$form, FormStateInterface $form_state): void {
$triggering_element = $form_state->getTriggeringElement();
// Extract the rule key from the button name.
$button_name = $triggering_element['#name'];
$rule_to_remove = str_replace('remove_', '', $button_name);
// Get current rules from form state.
$rules = $form_state->get('rules') ?? [];
// Remove the specific rule from the array.
$rules = array_filter($rules, function ($rule) use ($rule_to_remove) {
return $rule !== $rule_to_remove;
});
// Re-index the array to maintain sequential keys.
$rules = array_values($rules);
// Update form state with remaining rules.
$form_state->set('rules', $rules);
// Get the agent value and preserve it.
$agent = $form_state->getValue('ai_agent') ?? $form_state->get('ai_agent');
if ($agent) {
$form_state->set('ai_agent', $agent);
}
// Preserve the advanced_history setting.
$advanced_history = $form_state->getValue('advanced_history') ??
$form_state->getUserInput()['advanced_history'] ??
$form_state->get('advanced_history') ??
FALSE;
$form_state->setValue('advanced_history', $advanced_history);
$form_state->set('advanced_history', $advanced_history);
// Preserve chat history if in advanced mode.
if ($advanced_history) {
$user_input = $form_state->getUserInput();
if (isset($user_input['chat_history'])) {
$chat_history = [];
foreach ($user_input['chat_history'] as $value) {
if (is_array($value) && isset($value['role']) && isset($value['text'])) {
$chat_history[] = [
'role' => $value['role'],
'text' => $value['text'],
];
}
}
$form_state->set('chat_history', $chat_history);
}
}
$form_state->setRebuild(TRUE);
}
/**
* Ajax callback to show/hide the rules.
*/
public static function advancedHistoryCallback(array &$form, FormStateInterface $form_state): array {
return $form;
}
/**
* Ajax callback to add a new rule.
*/
public static function addRuleCallback(array &$form, FormStateInterface $form_state): array {
return $form;
}
/**
* Ajax callback to remove a rule.
*/
public static function removeRuleCallback(array &$form, FormStateInterface $form_state): array {
return $form;
}
/**
* The submit handler for the add chat history button.
*/
public static function addChatHistorySubmit(array &$form, FormStateInterface $form_state): void {
$input = $form_state->getUserInput();
foreach ($input['chat_history'] as $value) {
$chat_history[] = [
'role' => $value['role'],
'text' => $value['text'],
];
}
$chat_history[] = [
'role' => 'user',
'text' => '',
];
$form_state->set('chat_history', $chat_history);
$form_state->set('advanced_history', TRUE);
$form_state->setValue('advanced_history', TRUE);
$agent = $form_state->getValue('ai_agent');
$form_state->set('ai_agent', $agent);
$form_state->setRebuild(TRUE);
}
/**
* Ajax callback to add a new chat history.
*/
public static function addChatHistoryCallback(array &$form, FormStateInterface $form_state): array {
return $form;
}
/**
* Load from private temp store.
*
* @param array $form
* The form array.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The form state.
*/
protected function loadFromTempStore(array &$form, FormStateInterface $form_state): void {
$temp_store = $this->tempStore->get('ai_agents_test');
$import = $temp_store->get('import');
if ($import) {
$parsed_yaml = Yaml::parse($import);
foreach ($parsed_yaml as $key => $value) {
if ($key === 'label') {
$form_state->set('label', $value);
}
elseif ($key === 'description') {
$form_state->set('description', $value);
}
elseif ($key === 'config_reset') {
$form_state->set('config_reset', $value);
}
elseif ($key === 'ai_agent') {
$form_state->set('ai_agent', $value);
$form_state->setValue('ai_agent', $value);
}
elseif ($key === 'triggering_instructions') {
$form_state->set('triggering_instructions', $value);
$form_state->setValue('triggering_instructions', $value);
}
elseif ($key === 'tokens') {
$form_state->set('tokens', $value);
$form_state->setValue('tokens', $value);
}
elseif ($key === 'rules') {
$rules = Yaml::parse($value);
$response_rule = $rules['response_rule'] ?? [];
$form_state->set('response_rule', $response_rule);
unset($rules['response_rule']);
unset($rules['output_rules']);
$form_state->set('rules', array_keys($rules));
$form_state->setValue('rules', $rules);
}
elseif ($key === 'messages') {
$messages = Yaml::parse($value);
$form_state->set('messages', $messages);
if (count($messages) > 1) {
$form_state->setValue('advanced_history', TRUE);
$form_state->set('advanced_history', TRUE);
$chat_history = [];
foreach ($messages as $message) {
if (is_array($message) && !empty($message['content'])) {
$chat_history[] = [
'role' => $message['role'],
'text' => $message['content'],
];
}
}
$form_state->set('chat_history', $chat_history);
}
}
}
$form_state->setRebuild(TRUE);
}
}
/**
* Load from entity.
*
* @param array $form
* The form array.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The form state.
* @param \Drupal\ai_agents_test\AgentTestInterface $ai_agents_test
* The agent test entity.
*/
protected function loadFromEntity(array &$form, FormStateInterface $form_state, AgentTestInterface $ai_agents_test): void {
$form_state->set('label', $ai_agents_test->label());
$form_state->set('description', $ai_agents_test->description->value);
$form_state->set('ai_agent', $ai_agents_test->get('ai_agent')->entity->id());
$form_state->setValue('ai_agent', $ai_agents_test->get('ai_agent')->entity->id());
$rules = Yaml::parse($ai_agents_test->get('rules')->value);
$response_rule = $rules['response_rule'] ?? [];
unset($rules['response_rule']);
unset($rules['output_rules']);
$form_state->set('response_rule', $response_rule);
$form_state->set('rules', array_keys($rules));
$form_state->setValue('rules', $rules);
$form_state->set('triggering_instructions', $ai_agents_test->get('triggering_instructions')->value);
$form_state->setValue('triggering_instructions', $ai_agents_test->get('triggering_instructions')->value);
$form_state->set('config_reset', $ai_agents_test->get('config_reset')->value);
$form_state->set('tokens', $ai_agents_test->get('tokens')->value);
$form_state->setValue('tokens', $ai_agents_test->get('tokens')->value);
$messages = Yaml::parse($ai_agents_test->get('messages')->value);
$form_state->set('messages', $messages);
if (count($messages) > 1) {
$form_state->setValue('advanced_history', TRUE);
$form_state->set('advanced_history', TRUE);
$chat_history = [];
foreach ($messages as $message) {
if (is_array($message) && !empty($message['content'])) {
$chat_history[] = [
'role' => $message['role'],
'text' => $message['content'],
];
}
}
$form_state->set('chat_history', $chat_history);
}
}
}
