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
2 changes: 2 additions & 0 deletions data-machine-code.php
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,8 @@ function datamachine_code_load_chat_tools() {
return;
}

\DataMachineCode\Tools\AbilityToolProjections::register();

new \DataMachineCode\Tools\GitHubIssueTool();
new \DataMachineCode\Tools\GitHubPullRequestTool();
new \DataMachineCode\Tools\GitHubTools();
Expand Down
96 changes: 96 additions & 0 deletions inc/Tools/AbilityToolProjections.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
<?php
/**
* Ability-native model tool projections.
*
* @package DataMachineCode\Tools
*/

namespace DataMachineCode\Tools;

defined('ABSPATH') || exit;

class AbilityToolProjections {

/**
* Register DMC abilities as model-facing Data Machine tools.
*/
public static function register(): bool {
if ( ! function_exists('datamachine_register_ability_tool') ) {
return false;
}

foreach ( self::projected_tools() as $tool_name => $declaration ) {
datamachine_register_ability_tool($tool_name, $declaration);
}

return true;
}

/**
* Whether a tool name is registered through Data Machine's ability projection helper.
*/
public static function is_projected( string $tool_name ): bool {
return function_exists('datamachine_register_ability_tool') && isset(self::projected_tools()[ $tool_name ]);
}

/**
* Model-facing tool names mapped to canonical ability slugs.
*
* Tool names intentionally preserve the existing DMC model contract while
* schema and execution now come from the registered WordPress abilities.
*
* @return array<string,array<string,mixed>>
*/
public static function projected_tools(): array {
return array(
'workspace_path' => self::workspace('datamachine-code/workspace-path'),
'workspace_capabilities' => self::workspace('datamachine-code/workspace-capabilities'),
'workspace_list' => self::workspace('datamachine-code/workspace-list'),
'workspace_show' => self::workspace('datamachine-code/workspace-show'),
'workspace_ls' => self::workspace('datamachine-code/workspace-ls'),
'workspace_read' => self::workspace('datamachine-code/workspace-read'),
'workspace_grep' => self::workspace('datamachine-code/workspace-grep'),

'list_github_issues' => self::github('datamachine-code/list-github-issues'),
'get_github_issue' => self::github('datamachine-code/get-github-issue'),
'list_github_pulls' => self::github('datamachine-code/list-github-pulls'),
'get_github_pull' => self::github('datamachine-code/get-github-pull'),
'get_github_pull_files' => self::github('datamachine-code/list-github-pull-files'),
'get_github_check_runs' => self::github('datamachine-code/get-github-check-runs'),
'get_github_commit_statuses' => self::github('datamachine-code/get-github-commit-statuses'),
'get_github_actions_artifact' => self::github('datamachine-code/get-github-actions-artifact'),
'get_github_pull_review_context' => self::github('datamachine-code/get-github-pull-review-context'),
'github_repo_review_profile' => self::github('datamachine-code/get-github-repo-review-profile'),
'github_pr_documentation_impact' => self::github('datamachine-code/get-github-pr-documentation-impact'),
'list_github_tree' => self::github('datamachine-code/list-github-tree'),
'get_github_file' => self::github('datamachine-code/get-github-file'),
'list_github_repos' => self::github('datamachine-code/list-github-repos'),
);
}

/**
* Build a workspace projection declaration.
*
* @return array<string,mixed>
*/
private static function workspace( string $ability ): array {
return array(
'ability' => $ability,
'modes' => array( 'chat', 'pipeline' ),
);
}

/**
* Build a GitHub projection declaration.
*
* @return array<string,mixed>
*/
private static function github( string $ability ): array {
return array(
'ability' => $ability,
'access_level' => 'editor',
'modes' => array( 'chat', 'pipeline' ),
);
}

}
45 changes: 31 additions & 14 deletions inc/Tools/GitHubTools.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ class GitHubTools extends BaseTool
public function __construct()
{
$contexts = array( 'chat', 'pipeline' );
$this->registerTool('list_github_issues', array( $this, 'getListIssuesDefinition' ), $contexts, array( 'access_level' => 'editor', 'ability' => 'datamachine-code/list-github-issues' ));
$this->registerTool('get_github_issue', array( $this, 'getGetIssueDefinition' ), $contexts, array( 'access_level' => 'editor', 'ability' => 'datamachine-code/get-github-issue' ));
$this->registerProjectedToolFallback('list_github_issues', array( $this, 'getListIssuesDefinition' ), $contexts, array( 'access_level' => 'editor', 'ability' => 'datamachine-code/list-github-issues' ));
$this->registerProjectedToolFallback('get_github_issue', array( $this, 'getGetIssueDefinition' ), $contexts, array( 'access_level' => 'editor', 'ability' => 'datamachine-code/get-github-issue' ));
$this->registerTool('manage_github_issue', array( $this, 'getManageIssueDefinition' ), $contexts, array( 'access_level' => 'editor', 'ability' => 'datamachine-code/update-github-issue' ));
$this->registerTool('add_label_to_issue', array( $this, 'getAddLabelToIssueDefinition' ), $contexts, array( 'access_level' => 'editor', 'ability' => 'datamachine-code/add-github-labels' ));
$this->registerTool('remove_label_from_issue', array( $this, 'getRemoveLabelFromIssueDefinition' ), $contexts, array( 'access_level' => 'editor', 'ability' => 'datamachine-code/remove-github-label' ));
Expand All @@ -50,62 +50,62 @@ public function __construct()
'ability' => 'datamachine-code/cleanup-github-pull-request',
)
);
$this->registerTool('list_github_pulls', array( $this, 'getListPullsDefinition' ), $contexts, array( 'access_level' => 'editor', 'ability' => 'datamachine-code/list-github-pulls' ));
$this->registerTool(
$this->registerProjectedToolFallback('list_github_pulls', array( $this, 'getListPullsDefinition' ), $contexts, array( 'access_level' => 'editor', 'ability' => 'datamachine-code/list-github-pulls' ));
$this->registerProjectedToolFallback(
'get_github_pull', array( $this, 'getGetPullDefinition' ), $contexts, array(
'access_level' => 'editor',
'ability' => 'datamachine-code/get-github-pull',
)
);
$this->registerTool(
$this->registerProjectedToolFallback(
'get_github_pull_files', array( $this, 'getPullFilesDefinition' ), $contexts, array(
'access_level' => 'editor',
'ability' => 'datamachine-code/list-github-pull-files',
)
);
$this->registerTool(
$this->registerProjectedToolFallback(
'get_github_check_runs', array( $this, 'getCheckRunsDefinition' ), $contexts, array(
'access_level' => 'editor',
'ability' => 'datamachine-code/get-github-check-runs',
)
);
$this->registerTool(
$this->registerProjectedToolFallback(
'get_github_commit_statuses', array( $this, 'getCommitStatusesDefinition' ), $contexts, array(
'access_level' => 'editor',
'ability' => 'datamachine-code/get-github-commit-statuses',
)
);
$this->registerTool(
$this->registerProjectedToolFallback(
'get_github_actions_artifact', array( $this, 'getActionsArtifactDefinition' ), $contexts, array(
'access_level' => 'editor',
'ability' => 'datamachine-code/get-github-actions-artifact',
)
);
$this->registerTool(
$this->registerProjectedToolFallback(
'get_github_pull_review_context', array( $this, 'getPullReviewContextDefinition' ), $contexts, array(
'access_level' => 'editor',
'ability' => 'datamachine-code/get-github-pull-review-context',
)
);
$this->registerTool(
$this->registerProjectedToolFallback(
'github_repo_review_profile', array( $this, 'getRepoReviewProfileDefinition' ), $contexts, array(
'access_level' => 'editor',
'ability' => 'datamachine-code/get-github-repo-review-profile',
)
);
$this->registerTool(
$this->registerProjectedToolFallback(
'github_pr_documentation_impact', array( $this, 'getPullDocumentationImpactDefinition' ), $contexts, array(
'access_level' => 'editor',
'ability' => 'datamachine-code/get-github-pr-documentation-impact',
)
);
$this->registerTool(
$this->registerProjectedToolFallback(
'list_github_tree', array( $this, 'getListTreeDefinition' ), $contexts, array(
'access_level' => 'editor',
'ability' => 'datamachine-code/list-github-tree',
)
);
$this->registerTool(
$this->registerProjectedToolFallback(
'get_github_file', array( $this, 'getGetFileDefinition' ), $contexts, array(
'access_level' => 'editor',
'ability' => 'datamachine-code/get-github-file',
Expand All @@ -117,7 +117,24 @@ public function __construct()
'ability' => 'datamachine-code/create-or-update-github-file',
)
);
$this->registerTool('list_github_repos', array( $this, 'getListReposDefinition' ), $contexts, array( 'access_level' => 'editor', 'ability' => 'datamachine-code/list-github-repos' ));
$this->registerProjectedToolFallback('list_github_repos', array( $this, 'getListReposDefinition' ), $contexts, array( 'access_level' => 'editor', 'ability' => 'datamachine-code/list-github-repos' ));
}

/**
* Register a legacy wrapper only when Data Machine cannot project the ability directly.
*
* @param string $tool_id Model-facing tool name.
* @param callable $definition_callback Definition callback.
* @param array $contexts Tool contexts.
* @param array $options Tool metadata.
*/
private function registerProjectedToolFallback( string $tool_id, callable $definition_callback, array $contexts, array $options ): void
{
if ( class_exists(AbilityToolProjections::class) && AbilityToolProjections::is_projected($tool_id) ) {
return;
}

$this->registerTool($tool_id, $definition_callback, $contexts, $options);
}

/**
Expand Down
31 changes: 24 additions & 7 deletions inc/Tools/WorkspaceTools.php
Original file line number Diff line number Diff line change
Expand Up @@ -79,13 +79,13 @@ public function __construct()
$contexts = array( 'chat', 'pipeline' );
$policy_contexts = array( 'chat', 'pipeline' );
$policy_meta = array( 'requires_opt_in' => true );
$this->registerTool('workspace_path', array( $this, 'getPathDefinition' ), $contexts, array( 'ability' => 'datamachine-code/workspace-path' ));
$this->registerTool('workspace_capabilities', array( $this, 'getCapabilitiesDefinition' ), $contexts, array( 'ability' => 'datamachine-code/workspace-capabilities' ));
$this->registerTool('workspace_list', array( $this, 'getListDefinition' ), $contexts, array( 'ability' => 'datamachine-code/workspace-list' ));
$this->registerTool('workspace_show', array( $this, 'getShowDefinition' ), $contexts, array( 'ability' => 'datamachine-code/workspace-show' ));
$this->registerTool('workspace_ls', array( $this, 'getLsDefinition' ), $contexts, array( 'ability' => 'datamachine-code/workspace-ls' ));
$this->registerTool('workspace_read', array( $this, 'getReadDefinition' ), $contexts, array( 'ability' => 'datamachine-code/workspace-read' ));
$this->registerTool('workspace_grep', array( $this, 'getGrepDefinition' ), $contexts, array( 'ability' => 'datamachine-code/workspace-grep' ));
$this->registerProjectedToolFallback('workspace_path', array( $this, 'getPathDefinition' ), $contexts, array( 'ability' => 'datamachine-code/workspace-path' ));
$this->registerProjectedToolFallback('workspace_capabilities', array( $this, 'getCapabilitiesDefinition' ), $contexts, array( 'ability' => 'datamachine-code/workspace-capabilities' ));
$this->registerProjectedToolFallback('workspace_list', array( $this, 'getListDefinition' ), $contexts, array( 'ability' => 'datamachine-code/workspace-list' ));
$this->registerProjectedToolFallback('workspace_show', array( $this, 'getShowDefinition' ), $contexts, array( 'ability' => 'datamachine-code/workspace-show' ));
$this->registerProjectedToolFallback('workspace_ls', array( $this, 'getLsDefinition' ), $contexts, array( 'ability' => 'datamachine-code/workspace-ls' ));
$this->registerProjectedToolFallback('workspace_read', array( $this, 'getReadDefinition' ), $contexts, array( 'ability' => 'datamachine-code/workspace-read' ));
$this->registerProjectedToolFallback('workspace_grep', array( $this, 'getGrepDefinition' ), $contexts, array( 'ability' => 'datamachine-code/workspace-grep' ));
$this->registerTool('workspace_write', array( $this, 'getWriteDefinition' ), $policy_contexts, $policy_meta + array( 'ability' => 'datamachine-code/workspace-write' ));
$this->registerTool('workspace_edit', array( $this, 'getEditDefinition' ), $policy_contexts, $policy_meta + array( 'ability' => 'datamachine-code/workspace-edit' ));
$this->registerTool('workspace_apply_patch', array( $this, 'getApplyPatchDefinition' ), $policy_contexts, $policy_meta + array( 'ability' => 'datamachine-code/workspace-apply-patch' ));
Expand All @@ -104,6 +104,23 @@ public function __construct()
$this->registerTool('workspace_pr_rebase', array( $this, 'getPrRebaseDefinition' ), $policy_contexts, $policy_meta + array( 'ability' => 'datamachine-code/workspace-pr-rebase' ));
}

/**
* Register a legacy wrapper only when Data Machine cannot project the ability directly.
*
* @param string $tool_id Model-facing tool name.
* @param callable $definition_callback Definition callback.
* @param array $contexts Tool contexts.
* @param array $options Tool metadata.
*/
private function registerProjectedToolFallback( string $tool_id, callable $definition_callback, array $contexts, array $options ): void
{
if ( class_exists(AbilityToolProjections::class) && AbilityToolProjections::is_projected($tool_id) ) {
return;
}

$this->registerTool($tool_id, $definition_callback, $contexts, $options);
}

/**
* Dispatch tool calls to specific handlers.
*
Expand Down
Loading
Loading