fix(advisor): address review comments on tests, naming, docs, and get insight

Agent-Logs-Url: https://github.com/appwrite/appwrite/sessions/517a4586-d3e8-40b3-a3a9-f2d2ca82b0a0

Co-authored-by: abnegate <5857008+abnegate@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2026-05-11 01:59:31 +00:00
committed by GitHub
co-authored by abnegate
parent 8fa9ead279
commit bfd6cebbb0
10 changed files with 55 additions and 73 deletions
+1 -1
View File
@@ -427,7 +427,7 @@ jobs:
FunctionsSchedule,
GraphQL,
Health,
Insights,
Advisor,
Locale,
Projects,
Realtime,
+1 -1
View File
@@ -2102,7 +2102,7 @@ $platformCollections = [
'$id' => ID::custom('_key_project_target'),
'type' => Database::INDEX_KEY,
'attributes' => ['projectInternalId', 'targetType', 'target'],
'lengths' => [0, 0, 700],
'lengths' => [null, null, 700],
'orders' => [],
],
],
+5 -7
View File
@@ -362,23 +362,21 @@ return [
'category' => 'Other',
],
// Insights
// Advisor
'insights.read' => [
'description' => 'Access to read insights and their CTAs.',
'description' => 'Access to read insights under Advisor service.',
'category' => 'Other',
],
'insights.write' => [
'description' => 'Reserved for advisor insight ingestion outside CE.',
'description' => 'Reserved for Advisor insight ingestion outside CE.',
'category' => 'Other',
],
// Reports
'reports.read' => [
'description' => 'Access to read analyzer reports and their insights.',
'description' => 'Access to read reports under Advisor service.',
'category' => 'Other',
],
'reports.write' => [
'description' => 'Access to delete analyzer reports.',
'description' => 'Access to delete reports under Advisor service.',
'category' => 'Other',
],
];
+2 -2
View File
@@ -313,11 +313,11 @@ return [
'key' => 'advisor',
'name' => 'Advisor',
'subtitle' => 'The Advisor service surfaces actionable reports about your project resources, with CTA descriptors for one-click remediation in the console.',
'description' => '/docs/services/insights.md',
'description' => '/docs/services/advisor.md',
'controller' => '', // Uses modules
'sdk' => true,
'docs' => true,
'docsUrl' => 'https://appwrite.io/docs/server/insights',
'docsUrl' => 'https://appwrite.io/docs/server/advisor',
'tests' => true,
'optional' => true,
'icon' => '/images/services/insights.png',
+32 -49
View File
@@ -1,12 +1,12 @@
<?php
use Appwrite\Platform\Modules\Compute\Specification;
use Appwrite\Platform\Modules\Insights\Enums\InsightCTAMethod;
use Appwrite\Platform\Modules\Insights\Enums\InsightCTAService;
use Appwrite\Platform\Modules\Insights\Enums\InsightSeverity;
use Appwrite\Platform\Modules\Insights\Enums\InsightStatus;
use Appwrite\Platform\Modules\Insights\Enums\InsightType;
use Appwrite\Platform\Modules\Insights\Enums\ReportType;
use Appwrite\Platform\Modules\Insights\Enums\InsightCTAMethod as CTAMethod;
use Appwrite\Platform\Modules\Insights\Enums\InsightCTAService as CTAService;
use Appwrite\Platform\Modules\Insights\Enums\InsightSeverity as Severity;
use Appwrite\Platform\Modules\Insights\Enums\InsightStatus as Status;
use Appwrite\Platform\Modules\Insights\Enums\InsightType as Type;
use Appwrite\Platform\Modules\Insights\Enums\ReportType as Report;
use Utopia\System\System;
const APP_NAME = 'Appwrite';
@@ -435,67 +435,50 @@ const RESOURCE_TYPE_INSIGHTS = 'insights';
const RESOURCE_TYPE_REPORTS = 'reports';
// Insight types — engine-specific so the CTA action can reference the right public API.
const INSIGHT_TYPE_DATABASE_INDEX = InsightType::DATABASE_INDEX->value; // legacy databases.createIndex
const INSIGHT_TYPE_TABLES_DB_INDEX = InsightType::TABLES_DB_INDEX->value; // tablesDB.createIndex
const INSIGHT_TYPE_DOCUMENTS_DB_INDEX = InsightType::DOCUMENTS_DB_INDEX->value; // documentsDB.createIndex
const INSIGHT_TYPE_VECTORS_DB_INDEX = InsightType::VECTORS_DB_INDEX->value; // vectorsDB.createIndex
const INSIGHT_TYPE_DATABASE_PERFORMANCE = InsightType::DATABASE_PERFORMANCE->value;
const INSIGHT_TYPE_SITE_PERFORMANCE = InsightType::SITE_PERFORMANCE->value;
const INSIGHT_TYPE_SITE_ACCESSIBILITY = InsightType::SITE_ACCESSIBILITY->value;
const INSIGHT_TYPE_SITE_SEO = InsightType::SITE_SEO->value;
const INSIGHT_TYPE_FUNCTION_PERFORMANCE = InsightType::FUNCTION_PERFORMANCE->value;
const INSIGHT_TYPES = [
INSIGHT_TYPE_DATABASE_INDEX,
INSIGHT_TYPE_TABLES_DB_INDEX,
INSIGHT_TYPE_DOCUMENTS_DB_INDEX,
INSIGHT_TYPE_VECTORS_DB_INDEX,
INSIGHT_TYPE_DATABASE_PERFORMANCE,
INSIGHT_TYPE_SITE_PERFORMANCE,
INSIGHT_TYPE_SITE_ACCESSIBILITY,
INSIGHT_TYPE_SITE_SEO,
INSIGHT_TYPE_FUNCTION_PERFORMANCE,
Type::DATABASE_INDEX->value, // legacy databases.createIndex
Type::TABLES_DB_INDEX->value, // tablesDB.createIndex
Type::DOCUMENTS_DB_INDEX->value, // documentsDB.createIndex
Type::VECTORS_DB_INDEX->value, // vectorsDB.createIndex
Type::DATABASE_PERFORMANCE->value,
Type::SITE_PERFORMANCE->value,
Type::SITE_ACCESSIBILITY->value,
Type::SITE_SEO->value,
Type::FUNCTION_PERFORMANCE->value,
];
// Public API services (SDK namespaces) that an insight CTA's `service` can reference.
// Analyzers must pick the one matching the engine the resource lives in.
const INSIGHT_CTA_SERVICE_DATABASES = InsightCTAService::DATABASES->value; // legacy
const INSIGHT_CTA_SERVICE_TABLES_DB = InsightCTAService::TABLES_DB->value;
const INSIGHT_CTA_SERVICE_DOCUMENTS_DB = InsightCTAService::DOCUMENTS_DB->value;
const INSIGHT_CTA_SERVICE_VECTORS_DB = InsightCTAService::VECTORS_DB->value;
const INSIGHT_CTA_SERVICES = [
CTAService::DATABASES->value, // legacy
CTAService::TABLES_DB->value,
CTAService::DOCUMENTS_DB->value,
CTAService::VECTORS_DB->value,
];
// Public API method names that an insight CTA's `method` can reference for index suggestions.
const INSIGHT_CTA_METHOD_CREATE_INDEX = InsightCTAMethod::CREATE_INDEX->value;
const INSIGHT_CTA_METHODS = [
CTAMethod::CREATE_INDEX->value,
];
// Insight severities
const INSIGHT_SEVERITY_INFO = InsightSeverity::INFO->value;
const INSIGHT_SEVERITY_WARNING = InsightSeverity::WARNING->value;
const INSIGHT_SEVERITY_CRITICAL = InsightSeverity::CRITICAL->value;
const INSIGHT_SEVERITIES = [
INSIGHT_SEVERITY_INFO,
INSIGHT_SEVERITY_WARNING,
INSIGHT_SEVERITY_CRITICAL,
Severity::INFO->value,
Severity::WARNING->value,
Severity::CRITICAL->value,
];
// Insight statuses
const INSIGHT_STATUS_ACTIVE = InsightStatus::ACTIVE->value;
const INSIGHT_STATUS_DISMISSED = InsightStatus::DISMISSED->value;
const INSIGHT_STATUSES = [
INSIGHT_STATUS_ACTIVE,
INSIGHT_STATUS_DISMISSED,
Status::ACTIVE->value,
Status::DISMISSED->value,
];
// Report types
const REPORT_TYPE_LIGHTHOUSE = ReportType::LIGHTHOUSE->value;
const REPORT_TYPE_AUDIT = ReportType::AUDIT->value;
const REPORT_TYPE_DATABASE_ANALYZER = ReportType::DATABASE_ANALYZER->value;
const REPORT_TYPES = [
REPORT_TYPE_LIGHTHOUSE,
REPORT_TYPE_AUDIT,
REPORT_TYPE_DATABASE_ANALYZER,
Report::LIGHTHOUSE->value,
Report::AUDIT->value,
Report::DATABASE_ANALYZER->value,
];
// Resource types for Tokens
+3
View File
@@ -0,0 +1,3 @@
The Advisor service provides read access to analyzer reports and their nested insights for a project.
Use the reports endpoints to list and fetch analyzer runs, then use the insights endpoints to inspect individual findings attached to a report.
+1 -1
View File
@@ -38,7 +38,7 @@
<directory>./tests/e2e/Services/Messaging</directory>
<directory>./tests/e2e/Services/Migrations</directory>
<directory>./tests/e2e/Services/Project</directory>
<directory>./tests/e2e/Services/Insights</directory>
<directory>./tests/e2e/Services/Advisor</directory>
<file>./tests/e2e/Services/Functions/FunctionsBase.php</file>
<file>./tests/e2e/Services/Functions/FunctionsCustomServerTest.php</file>
<file>./tests/e2e/Services/Functions/FunctionsCustomClientTest.php</file>
@@ -34,7 +34,7 @@ class Get extends Action
->label('sdk', new Method(
namespace: 'advisor',
group: 'insights',
name: 'get',
name: 'getInsight',
description: <<<EOT
Get an insight by its unique ID, scoped to its parent report.
EOT,
@@ -67,16 +67,14 @@ class Get extends Action
throw new Exception(Exception::REPORT_NOT_FOUND);
}
$insight = $dbForPlatform->getDocument('insights', $insightId);
$insight = $report->find('$id', $insightId, 'insights');
if (
$insight->isEmpty()
|| $insight->getAttribute('projectInternalId') !== $project->getSequence()
|| $insight->getAttribute('reportInternalId') !== $report->getSequence()
) {
if (empty($insight)) {
throw new Exception(Exception::INSIGHT_NOT_FOUND);
}
$insight = $insight instanceof Document ? $insight : new Document($insight);
$response->dynamic($insight, Response::MODEL_INSIGHT);
}
}
@@ -1,11 +1,11 @@
<?php
namespace Tests\E2E\Services\Insights;
namespace Tests\E2E\Services\Advisor;
use Tests\E2E\Client;
use Utopia\Database\Helpers\ID;
trait InsightsBase
trait AdvisorBase
{
protected function serverHeaders(): array
{
@@ -1,6 +1,6 @@
<?php
namespace Tests\E2E\Services\Insights;
namespace Tests\E2E\Services\Advisor;
use Tests\E2E\Client;
use Tests\E2E\Scopes\ProjectCustom;
@@ -8,9 +8,9 @@ use Tests\E2E\Scopes\Scope;
use Tests\E2E\Scopes\SideServer;
use Utopia\Database\Helpers\ID;
class InsightsCustomServerTest extends Scope
class AdvisorCustomServerTest extends Scope
{
use InsightsBase;
use AdvisorBase;
use ProjectCustom;
use SideServer;