Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions inc/Abilities/SettingsAbilities.php
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ private function registerGetSettings(): void {
'properties' => array(
'success' => array( 'type' => 'boolean' ),
'settings' => array( 'type' => 'object' ),
'defaults' => array( 'type' => 'object' ),
'network_settings' => array( 'type' => 'object' ),
'global_tools' => array( 'type' => 'object' ),
'error' => array( 'type' => 'string' ),
),
Expand Down Expand Up @@ -323,6 +325,7 @@ public function checkPermission(): bool {
public function executeGetSettings( array $input ): array {
$input;
$settings = PluginSettings::all();
$defaults = PluginSettings::getDefaults();

$tool_manager = new \DataMachine\Engine\AI\Tools\ToolManager();
$global_tools = $tool_manager->get_global_tools();
Expand Down Expand Up @@ -369,15 +372,12 @@ public function executeGetSettings( array $input ): array {
'default_provider' => $settings['default_provider'] ?? '',
'default_model' => $settings['default_model'] ?? '',
'agent_models' => $settings['agent_models'] ?? array(),
'max_turns' => $settings['max_turns'] ?? 12,
'max_turns' => $settings['max_turns'] ?? $defaults['max_turns'],
'disabled_tools' => $settings['disabled_tools'] ?? array(),
'ai_provider_keys' => $masked_keys,
'queue_tuning' => $settings['queue_tuning'] ?? array(
'concurrent_batches' => 3,
'batch_size' => 25,
'time_limit' => 60,
),
'queue_tuning' => wp_parse_args( $settings['queue_tuning'] ?? array(), $defaults['queue_tuning'] ),
),
'defaults' => $defaults,
'network_settings' => array(
'default_provider' => $network_defaults['default_provider'] ?? '',
'default_model' => $network_defaults['default_model'] ?? '',
Expand Down Expand Up @@ -506,7 +506,7 @@ public function executeUpdateSettings( array $input ): array {

// Queue tuning settings for Action Scheduler
if ( isset( $input['queue_tuning'] ) && is_array( $input['queue_tuning'] ) ) {
$tuning = $all_settings['queue_tuning'] ?? array();
$tuning = wp_parse_args( $all_settings['queue_tuning'] ?? array(), PluginSettings::getDefaultQueueTuning() );

if ( isset( $input['queue_tuning']['concurrent_batches'] ) ) {
$batches = absint( $input['queue_tuning']['concurrent_batches'] );
Expand Down
8 changes: 4 additions & 4 deletions inc/Api/Chat/ChatOrchestrator.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public static function processChat(
): array|WP_Error {
$session_id = $options['session_id'] ?? null;
$selected_pipeline_id = (int) ( $options['selected_pipeline_id'] ?? 0 );
$max_turns = $options['max_turns'] ?? PluginSettings::get( 'max_turns', 12 );
$max_turns = $options['max_turns'] ?? PluginSettings::get( 'max_turns', PluginSettings::DEFAULT_MAX_TURNS );
$request_id = $options['request_id'] ?? null;

$chat_db = new ChatDatabase();
Expand Down Expand Up @@ -235,7 +235,7 @@ public static function processChat(
* @return array|WP_Error Response data array or WP_Error on failure.
*/
public static function processContinue( string $session_id, int $user_id ): array|WP_Error {
$max_turns = PluginSettings::get( 'max_turns', 12 );
$max_turns = PluginSettings::get( 'max_turns', PluginSettings::DEFAULT_MAX_TURNS );

$chat_db = new ChatDatabase();
$session = $chat_db->get_session( $session_id );
Expand Down Expand Up @@ -525,7 +525,7 @@ function () use ( $ability, $input ) {
* @param string $model AI model identifier.
* @param array $options Optional settings {
* @type bool $single_turn Whether to run single turn (default false).
* @type int $max_turns Maximum turns allowed (default 12).
* @type int $max_turns Maximum turns allowed (default 25).
* @type int $selected_pipeline_id Currently selected pipeline ID.
* @type string $agent_type Agent type for context (default 'chat').
* }
Expand All @@ -541,7 +541,7 @@ public static function executeConversationTurn(
array $options = array()
): array|WP_Error {
$single_turn = $options['single_turn'] ?? false;
$max_turns = $options['max_turns'] ?? PluginSettings::get( 'max_turns', 12 );
$max_turns = $options['max_turns'] ?? PluginSettings::get( 'max_turns', PluginSettings::DEFAULT_MAX_TURNS );
$selected_pipeline_id = $options['selected_pipeline_id'] ?? null;
$agent_type = $options['agent_type'] ?? 'chat';

Expand Down
6 changes: 1 addition & 5 deletions inc/Core/ActionScheduler/QueueTuning.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,7 @@
* @return array
*/
function datamachine_get_queue_tuning_defaults(): array {
return array(
'concurrent_batches' => 3, // AS defaults to 1
'batch_size' => 25, // AS defaults to 25 (keep same)
'time_limit' => 60, // AS defaults to 30
);
return PluginSettings::getDefaultQueueTuning();
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,25 +16,26 @@ import SettingsSaveBar, {
import ProviderModelSelector from '@shared/components/ai/ProviderModelSelector';
import { useProviders } from '@shared/queries/providers';

const DEFAULTS = {
const EMPTY_FORM = {
default_provider: '',
default_model: '',
agent_models: {},
site_context_enabled: false,
max_turns: 12,
max_turns: 0,
};

const AgentSettings = () => {
const { data, isLoading, error } = useSettings();
const { data: providersData } = useProviders();
const updateMutation = useUpdateSettings();
const maxTurnsDefault = data?.defaults?.max_turns ?? 1;
const [ pingSecret, setPingSecret ] = useState( '' );
const [ pingSecretVisible, setPingSecretVisible ] = useState( false );
const [ pingCopied, setPingCopied ] = useState( false );
const [ pingGenerating, setPingGenerating ] = useState( false );

const form = useFormState( {
initialData: DEFAULTS,
initialData: EMPTY_FORM,
onSubmit: ( formData ) => updateMutation.mutateAsync( formData ),
} );

Expand Down Expand Up @@ -90,11 +91,11 @@ const AgentSettings = () => {
agent_models: data.settings.agent_models || {},
site_context_enabled:
data.settings.site_context_enabled ?? false,
max_turns: data.settings.max_turns ?? 12,
max_turns: data.settings.max_turns ?? maxTurnsDefault,
} );
save.setHasChanges( false );
}
}, [ data ] ); // eslint-disable-line react-hooks/exhaustive-deps
}, [ data, maxTurnsDefault ] ); // eslint-disable-line react-hooks/exhaustive-deps

const updateField = ( field, value ) => {
form.updateField( field, value );
Expand Down Expand Up @@ -311,7 +312,7 @@ const AgentSettings = () => {
parseInt(
e.target.value,
10
) || 1
) || maxTurnsDefault
)
)
)
Expand Down
45 changes: 25 additions & 20 deletions inc/Core/Admin/Settings/assets/react/components/tabs/GeneralTab.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,17 @@ import SettingsSaveBar, {
useSaveStatus,
} from '@shared/components/SettingsSaveBar';

const DEFAULTS = {
const EMPTY_FORM = {
cleanup_job_data_on_failure: true,
file_retention_days: 7,
chat_retention_days: 90,
chat_ai_titles_enabled: true,
flows_per_page: 20,
jobs_per_page: 50,
queue_tuning: {
concurrent_batches: 3,
batch_size: 25,
time_limit: 60,
concurrent_batches: 0,
batch_size: 0,
time_limit: 0,
},
};

Expand All @@ -54,9 +54,14 @@ const QUEUE_LIMITS = {
const GeneralTab = () => {
const { data, isLoading, error } = useSettings();
const updateMutation = useUpdateSettings();
const queueDefaults = data?.defaults?.queue_tuning ?? {
concurrent_batches: 3,
batch_size: 25,
time_limit: 60,
};

const form = useFormState( {
initialData: DEFAULTS,
initialData: EMPTY_FORM,
onSubmit: ( formData ) => updateMutation.mutateAsync( formData ),
} );

Expand All @@ -69,23 +74,23 @@ const GeneralTab = () => {
if ( data?.settings ) {
form.reset( {
cleanup_job_data_on_failure:
data.settings.cleanup_job_data_on_failure ?? DEFAULTS.cleanup_job_data_on_failure,
data.settings.cleanup_job_data_on_failure ?? EMPTY_FORM.cleanup_job_data_on_failure,
file_retention_days:
data.settings.file_retention_days ?? DEFAULTS.file_retention_days,
data.settings.file_retention_days ?? EMPTY_FORM.file_retention_days,
chat_retention_days:
data.settings.chat_retention_days ?? DEFAULTS.chat_retention_days,
data.settings.chat_retention_days ?? EMPTY_FORM.chat_retention_days,
chat_ai_titles_enabled:
data.settings.chat_ai_titles_enabled ?? DEFAULTS.chat_ai_titles_enabled,
data.settings.chat_ai_titles_enabled ?? EMPTY_FORM.chat_ai_titles_enabled,
flows_per_page:
data.settings.flows_per_page ?? DEFAULTS.flows_per_page,
data.settings.flows_per_page ?? EMPTY_FORM.flows_per_page,
jobs_per_page:
data.settings.jobs_per_page ?? DEFAULTS.jobs_per_page,
data.settings.jobs_per_page ?? EMPTY_FORM.jobs_per_page,
queue_tuning:
data.settings.queue_tuning ?? DEFAULTS.queue_tuning,
data.settings.queue_tuning ?? queueDefaults,
} );
save.setHasChanges( false );
}
}, [ data ] ); // eslint-disable-line react-hooks/exhaustive-deps
}, [ data, queueDefaults ] ); // eslint-disable-line react-hooks/exhaustive-deps

/**
* Update a field and mark the form as changed.
Expand All @@ -100,7 +105,7 @@ const GeneralTab = () => {

const updateQueueTuning = ( key, rawValue ) => {
const { min, max, default: defaultVal } = QUEUE_LIMITS[ key ];
const value = clamp( rawValue, min, max, defaultVal );
const value = clamp( rawValue, min, max, queueDefaults[ key ] ?? defaultVal );
form.updateData( {
queue_tuning: {
...form.data.queue_tuning,
Expand Down Expand Up @@ -330,7 +335,7 @@ const GeneralTab = () => {
id="concurrent_batches"
value={
form.data.queue_tuning
?.concurrent_batches ?? 3
?.concurrent_batches ?? queueDefaults.concurrent_batches
}
onChange={ ( e ) =>
updateQueueTuning(
Expand All @@ -345,7 +350,7 @@ const GeneralTab = () => {
<p className="description">
Number of action batches that can run
simultaneously. Higher = faster processing,
but more server load. (1-10, default: 3)
but more server load. (1-10, default: { queueDefaults.concurrent_batches })
</p>
</fieldset>
</td>
Expand All @@ -359,7 +364,7 @@ const GeneralTab = () => {
type="number"
id="batch_size"
value={
form.data.queue_tuning?.batch_size ?? 25
form.data.queue_tuning?.batch_size ?? queueDefaults.batch_size
}
onChange={ ( e ) =>
updateQueueTuning(
Expand All @@ -375,7 +380,7 @@ const GeneralTab = () => {
Number of actions claimed per batch. For
AI-heavy workloads, smaller batches with
more concurrency often works better. (10-200,
default: 25)
default: { queueDefaults.batch_size })
</p>
</fieldset>
</td>
Expand All @@ -389,7 +394,7 @@ const GeneralTab = () => {
type="number"
id="time_limit"
value={
form.data.queue_tuning?.time_limit ?? 60
form.data.queue_tuning?.time_limit ?? queueDefaults.time_limit
}
onChange={ ( e ) =>
updateQueueTuning(
Expand All @@ -404,7 +409,7 @@ const GeneralTab = () => {
<p className="description">
Maximum seconds per batch execution. AI
steps with external API calls may need
longer limits. (15-300, default: 60)
longer limits. (15-300, default: { queueDefaults.time_limit })
</p>
</fieldset>
</td>
Expand Down
27 changes: 27 additions & 0 deletions inc/Core/PluginSettings.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,35 @@

class PluginSettings {

public const DEFAULT_MAX_TURNS = 25;

private static ?array $cache = null;

/**
* Get default queue tuning values.
*
* @return array{concurrent_batches:int,batch_size:int,time_limit:int}
*/
public static function getDefaultQueueTuning(): array {
return array(
'concurrent_batches' => 3,
'batch_size' => 25,
'time_limit' => 60,
);
}

/**
* Get centralized plugin defaults used by backend and admin UI.
*
* @return array{max_turns:int,queue_tuning:array{concurrent_batches:int,batch_size:int,time_limit:int}}
*/
public static function getDefaults(): array {
return array(
'max_turns' => self::DEFAULT_MAX_TURNS,
'queue_tuning' => self::getDefaultQueueTuning(),
);
}

/**
* Get all plugin settings (per-site only, no cascade).
*
Expand Down
2 changes: 1 addition & 1 deletion inc/Core/Steps/AI/AIStep.php
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ protected function executeStep(): array {

$pipeline_step_config = $this->engine->getPipelineStepConfig( $pipeline_step_id );

$max_turns = PluginSettings::get( 'max_turns', 12 );
$max_turns = PluginSettings::get( 'max_turns', PluginSettings::DEFAULT_MAX_TURNS );

// Resolve user_id and agent_id from engine snapshot (set by RunFlowAbility).
$job_snapshot = $this->engine->get( 'job' );
Expand Down
5 changes: 3 additions & 2 deletions inc/Engine/AI/AIConversationLoop.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

namespace DataMachine\Engine\AI;

use DataMachine\Core\PluginSettings;
use DataMachine\Engine\AI\Tools\ToolExecutor;

if ( ! defined( 'ABSPATH' ) ) {
Expand All @@ -34,7 +35,7 @@ class AIConversationLoop {
* @param string $model AI model identifier
* @param string $agent_type Agent type: 'pipeline' or 'chat'
* @param array $payload Step payload (job_id, flow_step_id, data, flow_step_config)
* @param int $max_turns Maximum conversation turns (default 12)
* @param int $max_turns Maximum conversation turns (default 25)
* @param bool $single_turn Execute exactly one turn and return (default false)
* @return array {
* @type array $messages Final conversation state
Expand All @@ -51,7 +52,7 @@ public function execute(
string $model,
string $agent_type,
array $payload = array(),
int $max_turns = 12,
int $max_turns = PluginSettings::DEFAULT_MAX_TURNS,
bool $single_turn = false
): array {
// Ensure max_turns is within reasonable bounds
Expand Down
Loading