Skip to content

Commit 94ec16f

Browse files
committed
Merge branch 'master' of github.com:apioo/fusio-impl into feat/issue-661-commit-log
# Conflicts: # src/Migrations/Version20230508210151.php # tests/Backend/Api/Connection/Database/Table/CollectionTest.php
2 parents b454a26 + 77319c6 commit 94ec16f

File tree

76 files changed

+3605
-1084
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

76 files changed

+3605
-1084
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ This overview shows all Fusio related composer dependencies and the build status
1616
| [fusio/cli](https://github.com/apioo/fusio-cli) | ![Status](https://github.com/apioo/fusio-cli/actions/workflows/ci.yml/badge.svg) |
1717
| [fusio/model](https://github.com/apioo/fusio-model) | ![Status](https://github.com/apioo/fusio-model/actions/workflows/ci.yml/badge.svg) |
1818
| [fusio/engine](https://github.com/apioo/fusio-engine) | ![Status](https://github.com/apioo/fusio-engine/actions/workflows/ci.yml/badge.svg) |
19+
| [fusio/adapter-ai](https://github.com/apioo/fusio-adapter-ai) | ![Status](https://github.com/apioo/fusio-adapter-ai/actions/workflows/ci.yml/badge.svg) |
1920
| [fusio/adapter-amqp](https://github.com/apioo/fusio-adapter-amqp) | ![Status](https://github.com/apioo/fusio-adapter-amqp/actions/workflows/ci.yml/badge.svg) |
2021
| [fusio/adapter-beanstalk](https://github.com/apioo/fusio-adapter-beanstalk) | ![Status](https://github.com/apioo/fusio-adapter-beanstalk/actions/workflows/ci.yml/badge.svg) |
2122
| [fusio/adapter-cli](https://github.com/apioo/fusio-adapter-cli) | ![Status](https://github.com/apioo/fusio-adapter-cli/actions/workflows/ci.yml/badge.svg) |

composer.json

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,6 @@
1010
"homepage": "https://chrisk.app"
1111
}
1212
],
13-
"scripts": {
14-
"tests": "@php vendor/phpunit/phpunit/phpunit --configuration phpunit.xml tests",
15-
"psalm": "@php vendor/vimeo/psalm/psalm"
16-
},
1713
"require": {
1814
"php": ">=8.1",
1915
"psx/framework": "^8.0",
@@ -22,6 +18,7 @@
2218
"fusio/cli": "^4.0",
2319
"fusio/model": "^4.0",
2420
"fusio/engine": "^6.0",
21+
"fusio/adapter-ai": "^0.1",
2522
"fusio/adapter-amqp": "^6.0",
2623
"fusio/adapter-beanstalk": "^6.0",
2724
"fusio/adapter-cli": "^6.0",
@@ -44,9 +41,9 @@
4441
"symfony/mailer": "^6.0|^7.0",
4542
"symfony/doctrine-messenger": "^6.0|^7.0",
4643
"dragonmantank/cron-expression": "^3.3",
47-
"phpstan/phpdoc-parser": "^1.0",
48-
"logiscape/mcp-sdk-php": "^1.2",
49-
"webonyx/graphql-php": "^15.24"
44+
"phpstan/phpdoc-parser": "^1.0|^2.0",
45+
"webonyx/graphql-php": "^15.24",
46+
"mcp/sdk": "^0.3"
5047
},
5148
"require-dev": {
5249
"phpunit/phpunit": "^12.0",
@@ -61,5 +58,10 @@
6158
"psr-4": {
6259
"Fusio\\Impl\\Tests\\": "tests/"
6360
}
61+
},
62+
"config": {
63+
"allow-plugins": {
64+
"php-http/discovery": false
65+
}
6466
}
6567
}

provider.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<?php
22

33
return [
4+
\Fusio\Adapter\Ai\Adapter::class,
45
\Fusio\Adapter\Amqp\Adapter::class,
56
\Fusio\Adapter\Beanstalk\Adapter::class,
67
\Fusio\Adapter\Cli\Adapter::class,

resources/container.php

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
use Fusio\Cli;
44
use Fusio\Engine\Action;
55
use Fusio\Engine\Adapter\ServiceBuilder;
6+
use Fusio\Engine\Agent\ToolsInterface;
67
use Fusio\Engine\ConnectorInterface;
78
use Fusio\Engine\DispatcherInterface;
89
use Fusio\Engine\Repository;
@@ -14,10 +15,13 @@
1415
use Fusio\Impl\Provider;
1516
use Fusio\Impl\Repository as ImplRepository;
1617
use Fusio\Impl\Service\Action\Producer;
18+
use Fusio\Impl\Service\Agent;
1719
use Fusio\Impl\Service\Event\Dispatcher;
20+
use Fusio\Impl\Service\Mcp\ReferenceHandler;
1821
use Fusio\Impl\Service\Tenant\LimiterInterface;
1922
use Fusio\Impl\Service\User\Captcha;
2023
use Fusio\Impl\Tenant\UnlimitedLimiter;
24+
use Mcp\Capability\Registry\ReferenceHandlerInterface;
2125
use Psr\Cache\CacheItemPoolInterface;
2226
use Psr\SimpleCache\CacheInterface;
2327
use PSX\Api;
@@ -30,10 +34,15 @@
3034
use PSX\Framework\Migration\DependencyFactoryFactory;
3135
use PSX\Http\Filter\UserAgentEnforcer;
3236
use PSX\Schema;
37+
use Symfony\AI\Agent\Toolbox\Toolbox;
38+
use Symfony\AI\Agent\Toolbox\ToolboxInterface;
39+
use Symfony\AI\Agent\Toolbox\ToolCallArgumentResolverInterface;
40+
use Symfony\AI\Agent\Toolbox\ToolFactoryInterface;
3341
use Symfony\Component\Cache\Psr16Cache;
3442
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
3543
use function Symfony\Component\DependencyInjection\Loader\Configurator\param;
3644
use function Symfony\Component\DependencyInjection\Loader\Configurator\service;
45+
use function Symfony\Component\DependencyInjection\Loader\Configurator\tagged_iterator;
3746

3847
return static function (ContainerConfigurator $container) {
3948
$services = ServiceBuilder::build($container);
@@ -62,6 +71,9 @@
6271
$services->set(Dispatcher::class);
6372
$services->alias(DispatcherInterface::class, Dispatcher::class);
6473

74+
$services->set(Agent\Tools::class);
75+
$services->alias(ToolsInterface::class, Agent\Tools::class);
76+
6577
$services->alias('test_connector', ConnectorInterface::class)
6678
->public();
6779

@@ -112,6 +124,19 @@
112124
$services->set(SDKgenConfig::class);
113125
$services->alias(Api\Repository\SDKgen\ConfigInterface::class, SDKgenConfig::class);
114126

127+
$services->set(Agent\OperationToolFactory::class);
128+
$services->alias(ToolFactoryInterface::class, Agent\OperationToolFactory::class);
129+
130+
$services->set(Agent\OperationToolCallArgumentResolver::class);
131+
$services->alias(ToolCallArgumentResolverInterface::class, Agent\OperationToolCallArgumentResolver::class);
132+
133+
$services->set(Agent\OperationTool::class)
134+
->tag('fusio.ai.tool');
135+
136+
$services->set(Toolbox::class)
137+
->arg('$tools', tagged_iterator('fusio.ai.tool'));
138+
$services->alias(ToolboxInterface::class, Toolbox::class);
139+
115140
// psx
116141
$services->set(Framework\Loader\RoutingParser\DatabaseParser::class);
117142
$services->set(Framework\Loader\RoutingParser\CompositeParser::class);

src/Backend/Action/Action/Execute.php

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
namespace Fusio\Impl\Backend\Action\Action;
2222

23+
use Doctrine\DBAL\Connection;
2324
use Fusio\Engine\ActionInterface;
2425
use Fusio\Engine\ContextInterface;
2526
use Fusio\Engine\ParametersInterface;
@@ -31,6 +32,8 @@
3132
use PSX\Http\Environment\HttpResponseInterface;
3233
use PSX\Http\Response;
3334
use PSX\Http\Writer\WriterInterface;
35+
use stdClass;
36+
use Throwable;
3437

3538
/**
3639
* Execute
@@ -39,14 +42,12 @@
3942
* @license http://www.apache.org/licenses/LICENSE-2.0
4043
* @link https://www.fusio-project.org
4144
*/
42-
class Execute implements ActionInterface
45+
readonly class Execute implements ActionInterface
4346
{
44-
private Action\Executor $actionExecutorService;
4547
private Converter $exceptionConverter;
4648

47-
public function __construct(Action\Executor $actionExecutorService)
49+
public function __construct(private Action\Executor $actionExecutorService, private Connection $connection)
4850
{
49-
$this->actionExecutorService = $actionExecutorService;
5051
$this->exceptionConverter = new Converter(true);
5152
}
5253

@@ -56,6 +57,8 @@ public function handle(RequestInterface $request, ParametersInterface $configura
5657

5758
assert($body instanceof ActionExecuteRequest);
5859

60+
$this->connection->beginTransaction();
61+
5962
try {
6063
$response = $this->actionExecutorService->execute(
6164
$request->get('action_id'),
@@ -74,30 +77,34 @@ public function handle(RequestInterface $request, ParametersInterface $configura
7477
$body = (string) $tempResponse->getBody();
7578
}
7679

77-
return [
80+
$return = [
7881
'statusCode' => $response->getStatusCode(),
7982
'headers' => $headers,
8083
'body' => $body,
8184
];
8285
} else {
83-
return [
86+
$return = [
8487
'statusCode' => 200,
85-
'headers' => new \stdClass(),
88+
'headers' => new stdClass(),
8689
'body' => $response,
8790
];
8891
}
89-
} catch (\Throwable $e) {
92+
} catch (Throwable $e) {
9093
if ($e instanceof MessageException) {
9194
$body = $e->getPayload();
9295
} else {
9396
$body = $this->exceptionConverter->convert($e);
9497
}
9598

96-
return [
99+
$return = [
97100
'statusCode' => 500,
98-
'headers' => new \stdClass(),
101+
'headers' => new stdClass(),
99102
'body' => $body,
100103
];
101104
}
105+
106+
$this->connection->rollBack();
107+
108+
return $return;
102109
}
103110
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<?php
2+
/*
3+
* Fusio - Self-Hosted API Management for Builders.
4+
* For the current version and information visit <https://www.fusio-project.org/>
5+
*
6+
* Copyright (c) Christoph Kappestein <christoph.kappestein@gmail.com>
7+
*
8+
* Licensed under the Apache License, Version 2.0 (the "License");
9+
* you may not use this file except in compliance with the License.
10+
* You may obtain a copy of the License at
11+
*
12+
* http://www.apache.org/licenses/LICENSE-2.0
13+
*
14+
* Unless required by applicable law or agreed to in writing, software
15+
* distributed under the License is distributed on an "AS IS" BASIS,
16+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17+
* See the License for the specific language governing permissions and
18+
* limitations under the License.
19+
*/
20+
21+
namespace Fusio\Impl\Backend\Action\Connection\Agent;
22+
23+
use Fusio\Engine\ActionInterface;
24+
use Fusio\Engine\Connector;
25+
use Fusio\Engine\RequestInterface;
26+
use Fusio\Impl\Service\System\FrameworkConfig;
27+
use PSX\Http\Exception as StatusCode;
28+
use PSX\Http\Exception\BadRequestException;
29+
use Symfony\AI\Agent\AgentInterface;
30+
31+
/**
32+
* AgentAbstract
33+
*
34+
* @author Christoph Kappestein <christoph.kappestein@gmail.com>
35+
* @license http://www.apache.org/licenses/LICENSE-2.0
36+
* @link https://www.fusio-project.org
37+
*/
38+
abstract readonly class AgentAbstract implements ActionInterface
39+
{
40+
public function __construct(private Connector $connector, private FrameworkConfig $frameworkConfig)
41+
{
42+
}
43+
44+
protected function getConnection(int $connectionId): AgentInterface
45+
{
46+
$connection = $this->connector->getConnection($connectionId);
47+
if (!$connection instanceof AgentInterface) {
48+
throw new BadRequestException('Provided an invalid connection');
49+
}
50+
51+
return $connection;
52+
}
53+
54+
protected function assertConnectionEnabled(): void
55+
{
56+
if (!$this->frameworkConfig->isConnectionEnabled()) {
57+
throw new StatusCode\ServiceUnavailableException('Agent is not enabled, please change the setting "fusio_connection" at the configuration.php to "true" in order to activate the agent');
58+
}
59+
}
60+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<?php
2+
/*
3+
* Fusio - Self-Hosted API Management for Builders.
4+
* For the current version and information visit <https://www.fusio-project.org/>
5+
*
6+
* Copyright (c) Christoph Kappestein <christoph.kappestein@gmail.com>
7+
*
8+
* Licensed under the Apache License, Version 2.0 (the "License");
9+
* you may not use this file except in compliance with the License.
10+
* You may obtain a copy of the License at
11+
*
12+
* http://www.apache.org/licenses/LICENSE-2.0
13+
*
14+
* Unless required by applicable law or agreed to in writing, software
15+
* distributed under the License is distributed on an "AS IS" BASIS,
16+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17+
* See the License for the specific language governing permissions and
18+
* limitations under the License.
19+
*/
20+
21+
namespace Fusio\Impl\Backend\Action\Connection\Agent;
22+
23+
use Fusio\Engine\Connector;
24+
use Fusio\Engine\ContextInterface;
25+
use Fusio\Engine\ParametersInterface;
26+
use Fusio\Engine\RequestInterface;
27+
use Fusio\Impl\Backend\View;
28+
use Fusio\Impl\Service\Agent\Intent;
29+
use Fusio\Impl\Service\System\FrameworkConfig;
30+
use PSX\Http\Environment\HttpResponse;
31+
use PSX\Http\Exception\BadRequestException;
32+
33+
/**
34+
* Get
35+
*
36+
* @author Christoph Kappestein <christoph.kappestein@gmail.com>
37+
* @license http://www.apache.org/licenses/LICENSE-2.0
38+
* @link https://www.fusio-project.org
39+
*/
40+
readonly class Get extends AgentAbstract
41+
{
42+
public function __construct(private View\Connection\Agent $view, Connector $connector, FrameworkConfig $frameworkConfig)
43+
{
44+
parent::__construct($connector, $frameworkConfig);
45+
}
46+
47+
public function handle(RequestInterface $request, ParametersInterface $configuration, ContextInterface $context): mixed
48+
{
49+
$this->assertConnectionEnabled();
50+
51+
$connectionId = (int) $request->get('connection_id');
52+
if (empty($connectionId)) {
53+
throw new BadRequestException('Provided no connection');
54+
}
55+
56+
$intent = Intent::tryFrom($request->get('intent') ?? '');
57+
58+
return new HttpResponse(200, [], $this->view->getCollection($connectionId, $intent, $context));
59+
}
60+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
<?php
2+
/*
3+
* Fusio - Self-Hosted API Management for Builders.
4+
* For the current version and information visit <https://www.fusio-project.org/>
5+
*
6+
* Copyright (c) Christoph Kappestein <christoph.kappestein@gmail.com>
7+
*
8+
* Licensed under the Apache License, Version 2.0 (the "License");
9+
* you may not use this file except in compliance with the License.
10+
* You may obtain a copy of the License at
11+
*
12+
* http://www.apache.org/licenses/LICENSE-2.0
13+
*
14+
* Unless required by applicable law or agreed to in writing, software
15+
* distributed under the License is distributed on an "AS IS" BASIS,
16+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17+
* See the License for the specific language governing permissions and
18+
* limitations under the License.
19+
*/
20+
21+
namespace Fusio\Impl\Backend\Action\Connection\Agent;
22+
23+
use Fusio\Engine\Connector;
24+
use Fusio\Engine\ContextInterface;
25+
use Fusio\Engine\ParametersInterface;
26+
use Fusio\Engine\RequestInterface;
27+
use Fusio\Impl\Service\System\FrameworkConfig;
28+
use Fusio\Impl\Table;
29+
use PSX\Http\Environment\HttpResponse;
30+
use PSX\Http\Exception\BadRequestException;
31+
32+
/**
33+
* Reset
34+
*
35+
* @author Christoph Kappestein <christoph.kappestein@gmail.com>
36+
* @license http://www.apache.org/licenses/LICENSE-2.0
37+
* @link https://www.fusio-project.org
38+
*/
39+
readonly class Reset extends AgentAbstract
40+
{
41+
public function __construct(private Table\Agent $agentTable, Connector $connector, FrameworkConfig $frameworkConfig)
42+
{
43+
parent::__construct($connector, $frameworkConfig);
44+
}
45+
46+
public function handle(RequestInterface $request, ParametersInterface $configuration, ContextInterface $context): mixed
47+
{
48+
$this->assertConnectionEnabled();
49+
50+
$connectionId = (int) $request->get('connection_id');
51+
if (empty($connectionId)) {
52+
throw new BadRequestException('Provided no connection');
53+
}
54+
55+
$this->agentTable->reset($context->getUser()->getId(), $connectionId);
56+
57+
return new HttpResponse(200, [], [
58+
'success' => true,
59+
'message' => 'Chat successfully reset',
60+
]);
61+
}
62+
}

0 commit comments

Comments
 (0)