Skip to content

Commit 046255a

Browse files
committed
register default agents
1 parent 48ab274 commit 046255a

File tree

21 files changed

+788
-41
lines changed

21 files changed

+788
-41
lines changed
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
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\EventListener;
22+
23+
use Fusio\Impl\Event;
24+
use Fusio\Impl\Table;
25+
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
26+
27+
/**
28+
* AgentUpdaterListener
29+
*
30+
* @author Christoph Kappestein <christoph.kappestein@gmail.com>
31+
* @license http://www.apache.org/licenses/LICENSE-2.0
32+
* @link https://www.fusio-project.org
33+
*/
34+
readonly class AgentUpdaterListener implements EventSubscriberInterface
35+
{
36+
public function __construct(private Table\Agent $agentTable)
37+
{
38+
}
39+
40+
public function onConnectionCreate(Event\Connection\CreatedEvent $event): void
41+
{
42+
if ($event->getConnection()->getClass() === 'Fusio.Adapter.Ai.Connection.Agent') {
43+
$this->agentTable->replaceDefaultConnection($event->getConnection()->getId());
44+
}
45+
}
46+
47+
public static function getSubscribedEvents(): array
48+
{
49+
return [
50+
Event\Connection\CreatedEvent::class => 'onConnectionCreate',
51+
];
52+
}
53+
}

src/Installation/DataBag.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -233,12 +233,12 @@ public function addActionCommit(string $action, string $user, string $commitHash
233233
];
234234
}
235235

236-
public function addAgent(string $category, string $connection, int $type, string $name, string $description, string $introduction, array $tools, string $outgoing, int $status = Table\Agent::STATUS_ACTIVE, ?array $metadata = null, ?string $date = null, ?string $tenantId = null): void
236+
public function addAgent(string $category, ?string $connection, int $type, string $name, string $description, string $introduction, array $tools, string $outgoing, int $status = Table\Agent::STATUS_ACTIVE, ?array $metadata = null, ?string $date = null, ?string $tenantId = null): void
237237
{
238238
$this->data['fusio_agent'][$name] = [
239239
'tenant_id' => $tenantId,
240240
'category_id' => $this->getReference('fusio_category', $category, $tenantId),
241-
'connection_id' => $this->getReference('fusio_connection', $connection, $tenantId),
241+
'connection_id' => $connection !== null ? $this->getReference('fusio_connection', $connection, $tenantId) : null,
242242
'status' => $status,
243243
'type' => $type,
244244
'name' => $name,

src/Installation/NewInstallation.php

Lines changed: 68 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -125,12 +125,61 @@ public static function getData(?string $tenantId = null): DataBag
125125
$bag->addUserScope('Administrator', 'consumer', tenantId: $tenantId);
126126
$bag->addUserScope('Administrator', 'authorization', tenantId: $tenantId);
127127
$bag->addUserScope('Administrator', 'default', tenantId: $tenantId);
128-
$bag->addPage('Overview', 'overview', self::readFile('overview.html'), Table\Page::STATUS_INVISIBLE, tenantId: $tenantId);
129-
$bag->addPage('Getting started', 'getting-started', self::readFile('getting-started.html'), tenantId: $tenantId);
130-
$bag->addPage('API', 'api', self::readFile('api.html'), tenantId: $tenantId);
131-
$bag->addPage('Authorization', 'authorization', self::readFile('authorization.html'), tenantId: $tenantId);
132-
$bag->addPage('Support', 'support', self::readFile('support.html'), tenantId: $tenantId);
133-
$bag->addPage('SDK', 'sdk', self::readFile('sdk.html'), tenantId: $tenantId);
128+
$bag->addPage('Overview', 'overview', self::readPage('overview.html'), Table\Page::STATUS_INVISIBLE, tenantId: $tenantId);
129+
$bag->addPage('Getting started', 'getting-started', self::readPage('getting-started.html'), tenantId: $tenantId);
130+
$bag->addPage('API', 'api', self::readPage('api.html'), tenantId: $tenantId);
131+
$bag->addPage('Authorization', 'authorization', self::readPage('authorization.html'), tenantId: $tenantId);
132+
$bag->addPage('Support', 'support', self::readPage('support.html'), tenantId: $tenantId);
133+
$bag->addPage('SDK', 'sdk', self::readPage('sdk.html'), tenantId: $tenantId);
134+
$bag->addAgent('default', null, Table\Agent::TYPE_GENERAL, 'Fusio-General', 'Helps to answer general questions about your Fusio instance', self::readAgent('general.md'), [
135+
'backend_operation_getAll',
136+
'backend_operation_get',
137+
'backend_action_getAll',
138+
'backend_action_get',
139+
'backend_action_getClasses',
140+
'backend_action_getForm',
141+
'backend_action_execute',
142+
'backend_action_get',
143+
'backend_schema_getAll',
144+
'backend_schema_get',
145+
'backend_connection_getAll',
146+
'backend_connection_get',
147+
'backend_connection_database_getTables',
148+
'backend_connection_database_getTable',
149+
'backend_connection_database_getRows',
150+
'backend_connection_database_getRow',
151+
'backend_connection_filesystem_getAll',
152+
'backend_connection_filesystem_get',
153+
'backend_connection_http_execute',
154+
'backend_connection_sdk_get',
155+
'backend_event_getAll',
156+
'backend_event_get',
157+
'backend_cronjob_getAll',
158+
'backend_cronjob_get',
159+
'backend_trigger_getAll',
160+
'backend_trigger_get',
161+
'backend_log_getAll',
162+
'backend_log_get',
163+
'backend_log_getAllErrors',
164+
'backend_log_getError',
165+
], '', tenantId: $tenantId);
166+
$bag->addAgent('default', null, Table\Agent::TYPE_ARCHITECT, 'Fusio-Architect', 'Helps to build complete operations, it uses internally the action, schema and database agent', self::readAgent('architect.md'), [], '', tenantId: $tenantId);
167+
$bag->addAgent('default', null, Table\Agent::TYPE_ACTION, 'Fusio-Action', 'Helps to develop custom action business logic', self::readAgent('action.md'), [
168+
'backend_action_getAll',
169+
'backend_action_get',
170+
'backend_connection_getAll',
171+
'backend_connection_get',
172+
'backend_database_getTables',
173+
'backend_database_getTable',
174+
], '', tenantId: $tenantId);
175+
$bag->addAgent('default', null, Table\Agent::TYPE_SCHEMA, 'Fusio-Schema', 'Helps to build new schemas to describe JSON payloads', self::readAgent('schema.md'), [
176+
'backend_schema_getAll',
177+
'backend_schema_get',
178+
], '', tenantId: $tenantId);
179+
$bag->addAgent('default', null, Table\Agent::TYPE_DATABASE, 'Fusio-Database', 'Helps to design database table schemas', self::readAgent('database.md'), [
180+
'backend_database_getTables',
181+
'backend_database_getTable',
182+
], '', tenantId: $tenantId);
134183

135184
foreach (self::getOperations() as $category => $operations) {
136185
$bag->addOperations($tenantId, $category, $operations);
@@ -2827,12 +2876,20 @@ private static function getOperations(): array
28272876
];
28282877
}
28292878

2830-
/**
2831-
* Reads files in new line neutral way that means we always use \n
2832-
*/
2833-
private static function readFile(string $file): string
2879+
private static function readPage(string $file): string
28342880
{
2835-
$lines = file(__DIR__ . '/resources/' . $file);
2881+
$lines = file(__DIR__ . '/resources/page/' . $file);
2882+
if ($lines === false) {
2883+
throw new \RuntimeException('Could not read file: ' . $file);
2884+
}
2885+
2886+
$lines = array_map('rtrim', $lines);
2887+
return implode("\n", $lines);
2888+
}
2889+
2890+
private static function readAgent(string $file): string
2891+
{
2892+
$lines = file(__DIR__ . '/resources/agent/' . $file);
28362893
if ($lines === false) {
28372894
throw new \RuntimeException('Could not read file: ' . $file);
28382895
}

src/Installation/Reference.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
use Doctrine\DBAL\Connection;
2424
use PSX\Sql\Condition;
2525
use PSX\Sql\Test\ResolvableInterface;
26+
use RuntimeException;
2627

2728
/**
2829
* Reference
@@ -64,7 +65,7 @@ public function resolve(Connection $connection): int
6465

6566
$id = (int) $connection->fetchOne($queryBuilder->getSQL(), $queryBuilder->getParameters());
6667
if (empty($id)) {
67-
throw new \RuntimeException('Could not resolve ' . $this->name . ' for table ' . $this->tableName);
68+
throw new RuntimeException('Could not resolve ' . $this->name . ' for table ' . $this->tableName);
6869
}
6970

7071
return $id;
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
The user intends to develop a new Fusio Action.
2+
3+
Your task is to transform the business logic described in the user message into PHP code.
4+
5+
Your response must ONLY contain the generated code wrapped in the following template.
6+
Do not include explanations, markdown formatting, or additional text.
7+
8+
<template>
9+
Action: [NAME]
10+
<?php
11+
12+
use Fusio\Worker;
13+
use Fusio\Engine;
14+
use Psr\Log\LoggerInterface;
15+
16+
return function(Worker\ExecuteRequest $request, Worker\ExecuteContext $context, Engine\ConnectorInterface $connector, Engine\Response\FactoryInterface $response, Engine\DispatcherInterface $dispatcher, LoggerInterface $logger) {
17+
18+
[CODE]
19+
20+
};
21+
</template>
22+
23+
Replace "[CODE]" with the generated PHP implementation.
24+
25+
Replace "[NAME]" with a short and precise action name derived from the business logic.
26+
The name must be lowercase and words must be separated by hyphens.
27+
28+
The generated code must always return a response using:
29+
30+
$response->build(statusCode, headers, body)
31+
32+
Normally you do not need to set a Content-Type header or use json_encode since Fusio automatically serializes the response body into JSON.
33+
34+
Only set a Content-Type header and serialize the body if the user explicitly requires a specific format such as XML.
35+
36+
--------------------------------
37+
38+
External Services
39+
40+
If the business logic requires interacting with an external service such as a database or HTTP API, use:
41+
42+
$connector->getConnection(connection_id)
43+
44+
to retrieve the connection.
45+
46+
You can retrieve available connections using the tool:
47+
backend_connection_getAll
48+
49+
Do not assume connection ids. Always verify them using the tool.
50+
51+
Connection mapping:
52+
53+
* Fusio.Adapter.Amqp.Connection.Amqp = AMQPStreamConnection (php-amqplib)
54+
* Fusio.Adapter.Beanstalk.Connection.Beanstalk = Pheanstalk
55+
* Fusio.Adapter.File.Connection.Filesystem = FilesystemOperator (Flysystem)
56+
* Fusio.Adapter.Http.Connection.Http = Client (Guzzle)
57+
* Fusio.Adapter.Redis.Connection.Redis = Client (Predis)
58+
* Fusio.Adapter.Smtp.Connection.Smtp = Mailer (Symfony Mailer)
59+
* Fusio.Adapter.Soap.Connection.Soap = SoapClient
60+
* Fusio.Impl.Connection.System = Connection (Doctrine DBAL)
61+
* Fusio.Adapter.Sql.Connection.Sql = Connection (Doctrine DBAL)
62+
* Fusio.Adapter.Sql.Connection.SqlAdvanced = Connection (Doctrine DBAL)
63+
* Fusio.Adapter.Stripe.Connection.Stripe = StripeClient
64+
65+
If the business logic requires a database but no connection is specified, use the "System" connection.
66+
67+
If the business logic requires access to a database table:
68+
69+
1. retrieve available tables using the tool backend_database_getTables
70+
2. retrieve the schema using backend_database_getTable
71+
72+
Use prepared statements when executing SQL queries.
73+
74+
--------------------------------
75+
76+
Available Methods
77+
78+
$request->getArguments()->get(name)
79+
$request->getArguments()->getOrDefault(name, default)
80+
$request->getPayload()
81+
82+
$context->getOperationId()
83+
$context->getBaseUrl()
84+
85+
$context->getUser()->getId()
86+
$context->getUser()->getName()
87+
$context->getUser()->getEmail()
88+
$context->getUser()->getPoints()
89+
90+
$connector->getConnection(connection_id)
91+
92+
$dispatcher->dispatch(event_name, payload)
93+
94+
$response->build(status_code, headers, body)
95+
96+
--------------------------------
97+
98+
Logging
99+
100+
Use the PSR-3 logger:
101+
102+
$logger->info()
103+
$logger->warning()
104+
$logger->error()
105+
106+
--------------------------------
107+
108+
Code Quality
109+
110+
The generated code should:
111+
112+
- be clear and readable
113+
- use proper variable names
114+
- include basic error handling when interacting with external services
115+
116+
Do not use APIs or helper methods that are not listed in this prompt.

0 commit comments

Comments
 (0)