adachsoft / ai-tool-call-plugin
Composer plugin that discovers ai-tool-call providers and generates a deterministic registry.
Installs: 2
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Forks: 0
Type:composer-plugin
pkg:composer/adachsoft/ai-tool-call-plugin
Requires
- php: ^8.3
- composer-plugin-api: ^2.0
- adachsoft/ai-tool-call: ^2.0
- adachsoft/collection: ^3.0
- nikic/php-parser: ^5.0
- psr/log: ^3.0
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.89
- phpstan/phpstan: ^2.1
- phpunit/phpunit: ^12.4
README
Composer plugin that discovers ai-tool-call tooling across installed packages and generates deterministic registry files used at runtime.
Requirements
- PHP >= 8.3
- Composer 2.x
- composer-plugin-api ^2.0, psr/log ^3.0, adachsoft/collection ^3.0
ToolFactory autodiscovery (recommended)
From version 0.3.0 the main integration path is ToolFactory-based autodiscovery.
1) Enable plugin in your project composer.json
{
"config": {
"allow-plugins": {
"adachsoft/ai-tool-call-plugin": true
}
}
}
2) Implement ToolFactory in your extension package
In your package that provides tools:
- implement
AdachSoft\AiToolCall\SPI\Factory\ToolFactoryInterface, - point to your package via normal Composer autoload (
autoload.psr-4).
Example:
namespace Vendor\Pkg;
use AdachSoft\AiToolCall\SPI\Factory\ToolFactoryInterface;
use AdachSoft\AiToolCall\SPI\ToolInterface;
use AdachSoft\AiToolCall\SPI\Dto\ToolDefinitionDto;
use AdachSoft\AiToolCall\SPI\Collection\ConfigMap;
final class MyToolFactory implements ToolFactoryInterface
{
public static function getToolClass(): string
{
return MyTool::class;
}
public static function createTool(object $serviceLocator): ToolInterface
{
// resolve dependencies from your container / service locator
return new MyTool();
}
}
final class MyTool implements ToolInterface
{
public static function getDefinition(): ToolDefinitionDto
{
return new ToolDefinitionDto(
name: 'my_tool',
description: 'My tool description',
parametersSchema: [],
tags: new \AdachSoft\AiToolCall\SPI\Collection\TagsCollection([]),
enabled: true,
);
}
// ... implement callTool(...)
}
3) Build ToolFactory registry
The plugin can build the registry in two ways:
- Automatically via Composer plugin hooks (
post-install-cmd,post-update-cmd). - Manually via CLI:
$ ./vendor/bin/ai-tool-call-tool-factory-registry-build
[ai-tool-call-plugin] ToolFactory registry written to /path/to/project/.generated/ai-tool-call-registry.php
The generated file has the following shape:
<?php
// .generated/ai-tool-call-registry.php
return [
'packages' => [
'vendor/pkg-a' => [
'Vendor\\Pkg\\MyToolFactory',
],
'vendor/other' => [
'Vendor\\Other\\AnotherFactory',
],
],
];
4) Runtime discovery
At runtime you use ToolFactoryRegistryReaderInterface + ToolFactoryDiscoveryInterface + DefaultToolingDiscovery to turn the registry into actual factories and tools.
- Registry reader loads
ToolFactoryRegistryDataDtofrom.generated/ai-tool-call-registry.php. DefaultToolFactoryDiscoveryturns factory FQCNs intoToolFactoryInterfaceinstances usingToolFactoryInstantiatorand an applicationServiceLocatorInterface.DefaultToolingDiscoverytakes discovered factories plusToolConfigProviderInterfaceand builds:configsByToolName(maptoolName => ConfigMap),DiscoveryErrorCollectionwith all discovery/config errors.
You can choose failure mode via ToolFactoryAutodiscoveryOptionsDto:
FailureModeEnum::FAIL_FAST– stop on first error, return partial data.FailureModeEnum::FAIL_SOFT– collect all errors and continue.
Legacy providers-based registry (backwards compatibility)
The original entry-file based mechanism is still supported for BC, but considered legacy.
1) In your extension package add entry-file and point it in composer.json:
extra.ai-tool-call.entry-file:"resources/ai-tool-call.php"resources/ai-tool-call.phpmust return array like:
<?php
return [
'providers' => [
['provider' => 'Vendor\\Pkg\\Provider\\MyToolProvider'],
],
];
2) Run composer update (or composer install) -> plugin generates .generated/ai-tool-call-registry.php in the legacy providers format.
3) At runtime use the legacy RegistryReader / RegistryWriter from Infrastructure\Registry if you still rely on the providers-based schema.
Debug helpers (bin)
ToolFactory registry debug
Use bin/ai-tool-call-registry-debug to quickly inspect the ToolFactory registry.
- Prints absolute path to the registry.
- Prints number of packages and number of factories per package.
- Exits with non-zero when registry is missing/invalid.
Example:
$ ./vendor/bin/ai-tool-call-registry-debug
[ai-tool-call-plugin] Registry path: /path/to/project/.generated/ai-tool-call-registry.php
Packages: 2
- vendor/pkg-a: 1 factories
- vendor/other: 2 factories
Notes
- No scanning of
vendor/at runtime – only generated registry is read. - Deterministic content (packages and factories sorted in the generated file).
- Legacy providers-based registry is kept for backwards compatibility but may be removed in a future major version.
Versioning
- Semantic Versioning via Git tags (do not set version in composer.json).