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
12 changes: 12 additions & 0 deletions .github/workflows/homeboy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,20 @@ jobs:
steps:
- uses: actions/checkout@v4

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.2'
extensions: mbstring, intl, pdo_sqlite, mysqli
tools: composer:v2
coverage: none

- name: Install project dependencies
run: composer install --no-interaction --prefer-dist

- uses: Extra-Chill/homeboy-action@v1
with:
version: '0.53.0'
extension: wordpress
commands: lint,test,audit
component: data-machine
Expand Down
12 changes: 6 additions & 6 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
"description": "WordPress plugin for automated data collection, AI processing, and multi-platform publishing",
"version": "0.10.2",
"license": "GPL-2.0-or-later",
"require": {
"php": ">=8.2",
"monolog/monolog": "^3.9",
"woocommerce/action-scheduler": "^3.9",
"chubes4/ai-http-client": "^2.0.13"
},
"require": {
"php": ">=8.2",
"monolog/monolog": "^3.9",
"woocommerce/action-scheduler": "^3.9",
"chubes4/ai-http-client": "^2.0.13"
},
"require-dev": {
"php-stubs/wordpress-stubs": "^6.9",
"wp-coding-standards/wpcs": "^3.1",
Expand Down
32 changes: 28 additions & 4 deletions inc/Abilities/AgentMemoryAbilities.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@ private function registerAbilities(): void {
'input_schema' => array(
'type' => 'object',
'properties' => array(
'user_id' => array(
'type' => 'integer',
'description' => 'WordPress user ID for multi-agent scoping. Defaults to 0 (shared agent).',
'default' => 0,
),
'section' => array(
'type' => 'string',
'description' => 'Section name to read (without ##). If omitted, returns the full file.',
Expand Down Expand Up @@ -78,6 +83,11 @@ private function registerAbilities(): void {
'input_schema' => array(
'type' => 'object',
'properties' => array(
'user_id' => array(
'type' => 'integer',
'description' => 'WordPress user ID for multi-agent scoping. Defaults to 0 (shared agent).',
'default' => 0,
),
'section' => array(
'type' => 'string',
'description' => 'Section name (without ##). Created if it does not exist.',
Expand Down Expand Up @@ -117,6 +127,11 @@ private function registerAbilities(): void {
'type' => 'object',
'required' => array( 'query' ),
'properties' => array(
'user_id' => array(
'type' => 'integer',
'description' => 'WordPress user ID for multi-agent scoping. Defaults to 0 (shared agent).',
'default' => 0,
),
'query' => array(
'type' => 'string',
'description' => 'Search term (case-insensitive substring match).',
Expand Down Expand Up @@ -162,6 +177,11 @@ private function registerAbilities(): void {
'input_schema' => array(
'type' => 'object',
'properties' => array(),
'user_id' => array(
'type' => 'integer',
'description' => 'WordPress user ID for multi-agent scoping. Defaults to 0 (shared agent).',
'default' => 0,
),
),
'output_schema' => array(
'type' => 'object',
Expand Down Expand Up @@ -195,7 +215,8 @@ private function registerAbilities(): void {
* @return array Result.
*/
public static function getMemory( array $input ): array {
$memory = new AgentMemory();
$user_id = (int) ( $input['user_id'] ?? 0 );
$memory = new AgentMemory( $user_id );
$section = $input['section'] ?? null;

if ( null === $section || '' === $section ) {
Expand All @@ -212,7 +233,8 @@ public static function getMemory( array $input ): array {
* @return array Result.
*/
public static function updateMemory( array $input ): array {
$memory = new AgentMemory();
$user_id = (int) ( $input['user_id'] ?? 0 );
$memory = new AgentMemory( $user_id );
$section = $input['section'];
$content = $input['content'];
$mode = $input['mode'];
Expand All @@ -231,7 +253,8 @@ public static function updateMemory( array $input ): array {
* @return array Search results.
*/
public static function searchMemory( array $input ): array {
$memory = new AgentMemory();
$user_id = (int) ( $input['user_id'] ?? 0 );
$memory = new AgentMemory( $user_id );
$query = $input['query'];
$section = $input['section'] ?? null;

Expand All @@ -245,7 +268,8 @@ public static function searchMemory( array $input ): array {
* @return array Result.
*/
public static function listSections( array $input ): array {
$memory = new AgentMemory();
$user_id = (int) ( $input['user_id'] ?? 0 );
$memory = new AgentMemory( $user_id );
return $memory->get_sections();
}
}
2 changes: 2 additions & 0 deletions inc/Abilities/Engine/RunFlowAbility.php
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ public function execute( array $input ): array {
'flow_id' => $flow_id,
'source' => 'pipeline',
'label' => $flow['flow_name'] ?? null,
'user_id' => (int) ( $flow['user_id'] ?? 0 ),
)
);
if ( ! $job_id ) {
Expand Down Expand Up @@ -167,6 +168,7 @@ public function execute( array $input ): array {
'job_id' => $job_id,
'flow_id' => $flow_id,
'pipeline_id' => $pipeline_id,
'user_id' => (int) ( $flow['user_id'] ?? 0 ),
'created_at' => current_time( 'mysql', true ),
),
'flow' => array(
Expand Down
67 changes: 50 additions & 17 deletions inc/Abilities/FileAbilities.php
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,11 @@ private function registerListFiles(): void {
'type' => array( 'string', 'null' ),
'description' => __( 'Flow step ID for flow-level files (e.g., "1-2" for pipeline 1, flow 2)', 'data-machine' ),
),
'user_id' => array(
'type' => 'integer',
'description' => __( 'WordPress user ID for multi-agent scoping. Defaults to 0 (shared agent).', 'data-machine' ),
'default' => 0,
),
'scope' => array(
'type' => array( 'string', 'null' ),
'description' => __( 'Scope for file operations. Use "agent" for agent directory files.', 'data-machine' ),
Expand Down Expand Up @@ -134,6 +139,11 @@ private function registerGetFile(): void {
'type' => array( 'string', 'null' ),
'description' => __( 'Flow step ID for flow-level files', 'data-machine' ),
),
'user_id' => array(
'type' => 'integer',
'description' => __( 'WordPress user ID for multi-agent scoping. Defaults to 0 (shared agent).', 'data-machine' ),
'default' => 0,
),
'scope' => array(
'type' => array( 'string', 'null' ),
'description' => __( 'Scope for file operations. Use "agent" for agent directory files.', 'data-machine' ),
Expand Down Expand Up @@ -178,6 +188,11 @@ private function registerWriteAgentFile(): void {
'type' => 'string',
'description' => __( 'Content to write to the file', 'data-machine' ),
),
'user_id' => array(
'type' => 'integer',
'description' => __( 'WordPress user ID for multi-agent scoping. Defaults to 0 (shared agent).', 'data-machine' ),
'default' => 0,
),
),
),
'output_schema' => array(
Expand Down Expand Up @@ -217,6 +232,11 @@ private function registerDeleteFile(): void {
'type' => array( 'string', 'null' ),
'description' => __( 'Flow step ID for flow-level files', 'data-machine' ),
),
'user_id' => array(
'type' => 'integer',
'description' => __( 'WordPress user ID for multi-agent scoping. Defaults to 0 (shared agent).', 'data-machine' ),
'default' => 0,
),
'scope' => array(
'type' => array( 'string', 'null' ),
'description' => __( 'Scope for file operations. Use "agent" for agent directory files.', 'data-machine' ),
Expand Down Expand Up @@ -307,6 +327,11 @@ private function registerUploadFile(): void {
'type' => array( 'string', 'null' ),
'description' => __( 'Flow step ID for flow-level files', 'data-machine' ),
),
'user_id' => array(
'type' => 'integer',
'description' => __( 'WordPress user ID for multi-agent scoping. Defaults to 0 (shared agent).', 'data-machine' ),
'default' => 0,
),
'scope' => array(
'type' => array( 'string', 'null' ),
'description' => __( 'Scope for file operations. Use "agent" for agent directory files.', 'data-machine' ),
Expand Down Expand Up @@ -347,9 +372,10 @@ public function checkPermission(): bool {
public function executeListFiles( array $input ): array {
$flow_step_id = $input['flow_step_id'] ?? null;
$scope = $input['scope'] ?? null;
$user_id = (int) ( $input['user_id'] ?? 0 );

if ( 'agent' === $scope ) {
return $this->listAgentFiles();
return $this->listAgentFiles( $user_id );
}

if ( ! $flow_step_id ) {
Expand All @@ -372,6 +398,7 @@ public function executeGetFile( array $input ): array {
$filename = $input['filename'] ?? null;
$flow_step_id = $input['flow_step_id'] ?? null;
$scope = $input['scope'] ?? null;
$user_id = (int) ( $input['user_id'] ?? 0 );

if ( empty( $filename ) ) {
return array(
Expand All @@ -383,7 +410,7 @@ public function executeGetFile( array $input ): array {
$filename = sanitize_file_name( $filename );

if ( 'agent' === $scope ) {
return $this->getAgentFile( $filename );
return $this->getAgentFile( $filename, $user_id );
}

if ( ! $flow_step_id ) {
Expand All @@ -405,6 +432,7 @@ public function executeGetFile( array $input ): array {
public function executeWriteAgentFile( array $input ): array {
$filename = $input['filename'] ?? null;
$content = $input['content'] ?? null;
$user_id = (int) ( $input['user_id'] ?? 0 );

if ( empty( $filename ) ) {
return array(
Expand All @@ -422,7 +450,7 @@ public function executeWriteAgentFile( array $input ): array {

$filename = sanitize_file_name( $filename );

return $this->writeAgentFile( $filename, $content );
return $this->writeAgentFile( $filename, $content, $user_id );
}

/**
Expand All @@ -435,6 +463,7 @@ public function executeDeleteFile( array $input ): array {
$filename = $input['filename'] ?? null;
$flow_step_id = $input['flow_step_id'] ?? null;
$scope = $input['scope'] ?? null;
$user_id = (int) ( $input['user_id'] ?? 0 );

if ( empty( $filename ) ) {
return array(
Expand All @@ -446,7 +475,7 @@ public function executeDeleteFile( array $input ): array {
$filename = sanitize_file_name( $filename );

if ( 'agent' === $scope ) {
return $this->deleteAgentFile( $filename );
return $this->deleteAgentFile( $filename, $user_id );
}

if ( ! $flow_step_id ) {
Expand Down Expand Up @@ -557,6 +586,7 @@ public function executeUploadFile( array $input ): array {
$file_data = $input['file_data'] ?? array();
$flow_step_id = $input['flow_step_id'] ?? null;
$scope = $input['scope'] ?? null;
$user_id = (int) ( $input['user_id'] ?? 0 );

if ( 'agent' !== $scope && ! $flow_step_id ) {
return array(
Expand Down Expand Up @@ -615,7 +645,7 @@ public function executeUploadFile( array $input ): array {
}

if ( 'agent' === $scope ) {
return $this->uploadToAgent( $file );
return $this->uploadToAgent( $file, $user_id );
}

return $this->uploadToFlow( $file, $flow_step_id );
Expand Down Expand Up @@ -905,12 +935,12 @@ private function deleteFileFromFlow( string $filename, string $flow_step_id ): a
*
* @return array Result with files.
*/
private function listAgentFiles(): array {
private function listAgentFiles( int $user_id = 0 ): array {
// Self-heal: ensure agent files exist before listing.
DirectoryManager::ensure_agent_files();

$directory_manager = new DirectoryManager();
$agent_dir = $directory_manager->get_agent_directory();
$agent_dir = $directory_manager->get_agent_directory( $user_id );

if ( ! file_exists( $agent_dir ) ) {
return array(
Expand Down Expand Up @@ -943,7 +973,7 @@ private function listAgentFiles(): array {
}

// Include daily memory summary if the directory exists.
$daily = new DailyMemory();
$daily = new DailyMemory( $user_id );
$daily_result = $daily->list_all();

if ( ! empty( $daily_result['months'] ) ) {
Expand Down Expand Up @@ -974,12 +1004,12 @@ private function listAgentFiles(): array {
* @param string $filename Filename to retrieve.
* @return array Result with file data.
*/
private function getAgentFile( string $filename ): array {
private function getAgentFile( string $filename, int $user_id = 0 ): array {
// Self-heal: ensure agent files exist before retrieval.
DirectoryManager::ensure_agent_files();

$directory_manager = new DirectoryManager();
$agent_dir = $directory_manager->get_agent_directory();
$agent_dir = $directory_manager->get_agent_directory( $user_id );
$filepath = "{$agent_dir}/{$filename}";

if ( ! file_exists( $filepath ) ) {
Expand Down Expand Up @@ -1009,7 +1039,7 @@ private function getAgentFile( string $filename ): array {
* @param string $filename Filename to delete.
* @return array Result with deletion status.
*/
private function deleteAgentFile( string $filename ): array {
private function deleteAgentFile( string $filename, int $user_id = 0 ): array {
if ( in_array( $filename, self::PROTECTED_FILES, true ) ) {
return array(
'success' => false,
Expand All @@ -1018,7 +1048,7 @@ private function deleteAgentFile( string $filename ): array {
}

$directory_manager = new DirectoryManager();
$agent_dir = $directory_manager->get_agent_directory();
$agent_dir = $directory_manager->get_agent_directory( $user_id );
$filepath = "{$agent_dir}/{$filename}";

if ( ! file_exists( $filepath ) ) {
Expand All @@ -1034,7 +1064,10 @@ private function deleteAgentFile( string $filename ): array {
'datamachine_log',
'info',
'Agent file deleted via ability',
array( 'filename' => $filename )
array(
'filename' => $filename,
'user_id' => $user_id,
)
);

return array(
Expand All @@ -1053,7 +1086,7 @@ private function deleteAgentFile( string $filename ): array {
* @param string $content Content to write.
* @return array Result with write status.
*/
private function writeAgentFile( string $filename, string $content ): array {
private function writeAgentFile( string $filename, string $content, int $user_id = 0 ): array {
if ( in_array( $filename, self::PROTECTED_FILES, true ) && '' === trim( $content ) ) {
return array(
'success' => false,
Expand All @@ -1062,7 +1095,7 @@ private function writeAgentFile( string $filename, string $content ): array {
}

$directory_manager = new DirectoryManager();
$agent_dir = $directory_manager->get_agent_directory();
$agent_dir = $directory_manager->get_agent_directory( $user_id );

if ( ! $directory_manager->ensure_directory_exists( $agent_dir ) ) {
return array(
Expand Down Expand Up @@ -1111,9 +1144,9 @@ private function writeAgentFile( string $filename, string $content ): array {
* @param array $file File data.
* @return array Result with files list.
*/
private function uploadToAgent( array $file ): array {
private function uploadToAgent( array $file, int $user_id = 0 ): array {
$directory_manager = new DirectoryManager();
$agent_dir = $directory_manager->get_agent_directory();
$agent_dir = $directory_manager->get_agent_directory( $user_id );

if ( ! $directory_manager->ensure_directory_exists( $agent_dir ) ) {
return array(
Expand Down
Loading
Loading