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
13 changes: 4 additions & 9 deletions plugins/data-machine-events/data-machine-events.php
Original file line number Diff line number Diff line change
Expand Up @@ -122,15 +122,10 @@ function datamachine_get_event_timing( int $post_id ): string {
require_once DATA_MACHINE_EVENTS_PLUGIN_DIR . 'inc/Core/event-tool-guard.php';
\DataMachineEvents\Core\register_event_tool_guard();

// Give event-upsert AI steps today's date and the shared year-inference rule so
// year-less venue dates resolve instead of being deferred (issue #3882).
require_once DATA_MACHINE_EVENTS_PLUGIN_DIR . 'inc/Core/event-date-context-directive.php';
\DataMachineEvents\Core\EventDateContextDirective::register();

// Tell event-upsert AI steps on single-venue flows that location is settled,
// so venues in neighbouring towns are not rejected as off-market (#3956).
require_once DATA_MACHINE_EVENTS_PLUGIN_DIR . 'inc/Core/pinned-venue-context-directive.php';
\DataMachineEvents\Core\PinnedVenueContextDirective::register();
// Event-upsert AI step directives: today's date for year-less venue dates
// (#3882) and settled location for pinned-venue flows (#3956).
require_once DATA_MACHINE_EVENTS_PLUGIN_DIR . 'inc/Core/event-ai-directives.php';
\DataMachineEvents\Core\register_event_ai_directives();

// Load REST API routes (modular)
if ( file_exists( DATA_MACHINE_EVENTS_PLUGIN_DIR . 'inc/Api/Routes.php' ) ) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,34 +15,20 @@

namespace DataMachineEvents\Core;

use DataMachine\Engine\AI\Directives\DirectiveInterface;

if ( ! defined( 'ABSPATH' ) ) {
exit;
}

/**
* Supplies today's date and the year-inference rule to event-upsert AI steps.
*/
final class EventDateContextDirective {
final class EventDateContextDirective implements DirectiveInterface {

/** Days a year-less date may sit in the past before it rolls to next year. Mirrors BaseExtractor::PAST_DATE_GRACE_DAYS. */
public const PAST_DATE_GRACE_DAYS = 14;

/**
* Register the directive with Data Machine for pipeline AI steps.
*/
public static function register(): void {
add_filter(
'datamachine_directives',
static function ( $directives ) {
$directives[] = array(
'class' => self::class,
'priority' => 55,
'modes' => array( 'pipeline' ),
);
return $directives;
}
);
}

/**
* Directive outputs for the Data Machine directive system.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,31 +14,17 @@

namespace DataMachineEvents\Core;

use DataMachine\Engine\AI\Directives\DirectiveInterface;

if ( ! defined( 'ABSPATH' ) ) {
exit;
}

/**
* Supplies pinned-venue location context to event-upsert AI steps.
*/
final class PinnedVenueContextDirective {
final class PinnedVenueContextDirective implements DirectiveInterface {

/**
* Register the directive with Data Machine for pipeline AI steps.
*/
public static function register(): void {
add_filter(
'datamachine_directives',
static function ( $directives ) {
$directives[] = array(
'class' => self::class,
'priority' => 56,
'modes' => array( 'pipeline' ),
);
return $directives;
}
);
}

/**
* Directive outputs for the Data Machine directive system.
Expand Down
51 changes: 51 additions & 0 deletions plugins/data-machine-events/inc/Core/event-ai-directives.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php
/**
* Register the events AI directives with Data Machine.
*
* Data Machine's PromptBuilder only runs directive classes that implement
* DirectiveInterface. This plugin loads before Data Machine, so the directive
* classes live in PSR-4 files and are autoloaded when PromptBuilder resolves
* them. Registration only names them, so loading this file never needs the
* interface (#3959).
*
* @package DataMachineEvents\Core
*/

namespace DataMachineEvents\Core;

if ( ! defined( 'ABSPATH' ) ) {
exit;
}

/**
* Directive classes for pipeline AI steps, with their priorities.
*
* @return array<string, int>
*/
function event_ai_directive_classes(): array {
return array(
// Today's date and the shared year-inference rule (#3882).
EventDateContextDirective::class => 55,
// A pinned venue's location is settled (#3956).
PinnedVenueContextDirective::class => 56,
);
}

/**
* Add the events directives to Data Machine's directive registry.
*/
function register_event_ai_directives(): void {
add_filter(
'datamachine_directives',
static function ( $directives ) {
foreach ( event_ai_directive_classes() as $class => $priority ) {
$directives[] = array(
'class' => $class,
'priority' => $priority,
'modes' => array( 'pipeline' ),
);
}
return $directives;
}
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<?php
/**
* Events AI directives reach a real Data Machine prompt (issue #3959).
*
* The directive unit tests call get_outputs() directly, which passed while
* PromptBuilder silently skipped both classes for not implementing
* DirectiveInterface. These tests go through PromptBuilder itself.
*
* @package DataMachineEvents\Tests\Unit
*/

namespace DataMachineEvents\Tests\Unit;

use DataMachine\Engine\AI\Directives\DirectiveInterface;
use DataMachine\Engine\AI\PromptBuilder;
use DataMachineEvents\Core\EventDateContextDirective;
use DataMachineEvents\Core\PinnedVenueContextDirective;
use WP_UnitTestCase;

class EventAiDirectivesPromptTest extends WP_UnitTestCase {

public function test_directives_implement_data_machine_interface(): void {
$this->assertTrue( is_subclass_of( EventDateContextDirective::class, DirectiveInterface::class ) );
$this->assertTrue( is_subclass_of( PinnedVenueContextDirective::class, DirectiveInterface::class ) );
}

public function test_registered_directives_render_into_pipeline_prompt(): void {
$builder = new PromptBuilder();
$builder->setMessages( array() )->setTools(
array(
'upsert_event' => array(
'name' => 'upsert_event',
'handler' => 'upsert_event',
),
)
);

foreach ( apply_filters( 'datamachine_directives', array() ) as $directive ) {
if ( in_array( $directive['class'] ?? '', array( EventDateContextDirective::class, PinnedVenueContextDirective::class ), true ) ) {
$builder->addDirective( $directive['class'], (int) $directive['priority'], $directive['modes'] );
}
}

$payload = array(
'engine_data' => array(
'flow_config' => array(
'1_step_0_9' => array(
'handler_configs' => array(
'universal_web_scraper' => array(
'venue_name' => 'Stumble Inn Bar & Grill',
'venue_city' => 'Londonderry',
'venue_state' => 'NH',
),
),
),
'1_step_2_9' => array( 'handler_configs' => array( 'upsert_event' => array( 'taxonomy_venue_selection' => '117854' ) ) ),
),
),
);

$request = $builder->buildDetailed( array( 'pipeline' ), 'openai', $payload );

$this->assertContains( 'EventDateContextDirective', $request['applied_directives'] );
$this->assertContains( 'PinnedVenueContextDirective', $request['applied_directives'] );

$text = wp_json_encode( $request['messages'] );
$this->assertStringContainsString( 'Event date context', $text );
$this->assertStringContainsString( 'Stumble Inn Bar & Grill (Londonderry, NH)', $text );
}
}
Loading