Skip to content

Commit 97d76f8

Browse files
committed
refactor(super-magic-module): streamline TaskAppService and TaskDomainService by integrating messageId handling and removing obsolete ToolFileIdMatcher references
1 parent f1d4615 commit 97d76f8

File tree

10 files changed

+419
-263
lines changed

10 files changed

+419
-263
lines changed
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
/**
5+
* Copyright (c) The Magic , Distributed under the software license
6+
*/
7+
use Hyperf\Database\Migrations\Migration;
8+
use Hyperf\Database\Schema\Blueprint;
9+
use Hyperf\Database\Schema\Schema;
10+
use Hyperf\DbConnection\Db;
11+
12+
return new class extends Migration {
13+
/**
14+
* Run the migrations.
15+
*/
16+
public function up(): void
17+
{
18+
if (!Schema::hasTable('magic_super_agent_message')) {
19+
return;
20+
}
21+
22+
Schema::table('magic_super_agent_message', function (Blueprint $table) {
23+
// Check if idx_id index exists
24+
if (!$this->indexExists('magic_super_agent_message', 'idx_id')) {
25+
$table->index(['id'], 'idx_id');
26+
}
27+
28+
// Check if idx_topic_show_deleted index exists
29+
if (!$this->indexExists('magic_super_agent_message', 'idx_topic_show_deleted')) {
30+
$table->index(['topic_id', 'show_in_ui', 'deleted_at'], 'idx_topic_show_deleted');
31+
}
32+
});
33+
}
34+
35+
/**
36+
* Reverse the migrations.
37+
*/
38+
public function down(): void
39+
{
40+
if (!Schema::hasTable('magic_super_agent_message')) {
41+
return;
42+
}
43+
44+
Schema::table('magic_super_agent_message', function (Blueprint $table) {
45+
// Drop indexes if they exist
46+
if ($this->indexExists('magic_super_agent_message', 'idx_id')) {
47+
$table->dropIndex('idx_id');
48+
}
49+
50+
if ($this->indexExists('magic_super_agent_message', 'idx_topic_show_deleted')) {
51+
$table->dropIndex('idx_topic_show_deleted');
52+
}
53+
});
54+
}
55+
56+
/**
57+
* Check if index exists on table
58+
*/
59+
private function indexExists(string $tableName, string $indexName): bool
60+
{
61+
$database = config('databases.default.database');
62+
63+
$result = Db::select("
64+
SELECT COUNT(*) as count
65+
FROM information_schema.statistics
66+
WHERE table_schema = ?
67+
AND table_name = ?
68+
AND index_name = ?
69+
", [$database, $tableName, $indexName]);
70+
71+
return $result[0]->count > 0;
72+
}
73+
};
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
/**
5+
* Copyright (c) The Magic , Distributed under the software license
6+
*/
7+
use Hyperf\Database\Migrations\Migration;
8+
use Hyperf\Database\Schema\Schema;
9+
use Hyperf\DbConnection\Db;
10+
11+
return new class extends Migration {
12+
/**
13+
* Run the migrations.
14+
*/
15+
public function up(): void
16+
{
17+
// 只有当表存在时才执行索引操作
18+
if (Schema::hasTable('magic_super_agent_message')) {
19+
// 检查并创建 idx_message_id 索引
20+
$this->createIndexIfNotExists(
21+
'magic_super_agent_message',
22+
'idx_message_id',
23+
'CREATE INDEX idx_message_id ON `magic_super_agent_message` (message_id)'
24+
);
25+
}
26+
}
27+
28+
/**
29+
* Reverse the migrations.
30+
*/
31+
public function down(): void
32+
{
33+
if (Schema::hasTable('magic_super_agent_message')) {
34+
// 删除索引
35+
$this->dropIndexIfExists('magic_super_agent_message', 'idx_message_id');
36+
}
37+
}
38+
39+
/**
40+
* 检查索引是否存在,如果不存在则创建索引.
41+
*
42+
* @param string $table 表名
43+
* @param string $indexName 索引名称
44+
* @param string $createStatement 创建索引的SQL语句
45+
*/
46+
private function createIndexIfNotExists(string $table, string $indexName, string $createStatement): void
47+
{
48+
// 检查索引是否存在
49+
$indexExists = Db::select(
50+
"SHOW INDEX FROM `{$table}` WHERE Key_name = ?",
51+
[$indexName]
52+
);
53+
54+
// 只有当索引不存在时才创建
55+
if (empty($indexExists)) {
56+
// 创建索引
57+
Db::statement($createStatement);
58+
}
59+
}
60+
61+
/**
62+
* 如果索引存在则删除.
63+
*
64+
* @param string $table 表名
65+
* @param string $indexName 索引名称
66+
*/
67+
private function dropIndexIfExists(string $table, string $indexName): void
68+
{
69+
// 检查索引是否存在
70+
$indexExists = Db::select(
71+
"SHOW INDEX FROM `{$table}` WHERE Key_name = ?",
72+
[$indexName]
73+
);
74+
75+
if (! empty($indexExists)) {
76+
// 删除现有索引
77+
Db::statement("DROP INDEX `{$indexName}` ON `{$table}`");
78+
}
79+
}
80+
};

backend/super-magic-module/src/Application/SuperAgent/Service/TaskAppService.php

Lines changed: 11 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,8 @@
4848
use Dtyq\SuperMagic\Infrastructure\ExternalAPI\Sandbox\SandboxResult;
4949
use Dtyq\SuperMagic\Infrastructure\ExternalAPI\Sandbox\SandboxStruct;
5050
use Dtyq\SuperMagic\Infrastructure\ExternalAPI\Sandbox\Volcengine\SandboxService;
51-
// use Dtyq\BillingManager\Service\QuotaService;
5251
use Dtyq\SuperMagic\Infrastructure\ExternalAPI\Sandbox\WebSocket\WebSocketSession;
53-
use Dtyq\SuperMagic\Infrastructure\Utils\ToolFileIdMatcher;
52+
use Dtyq\SuperMagic\Infrastructure\Utils\ToolProcessor;
5453
use Dtyq\SuperMagic\Interfaces\SuperAgent\DTO\TopicTaskMessageDTO;
5554
use Error;
5655
use Exception;
@@ -70,11 +69,6 @@ class TaskAppService extends AbstractAppService
7069
*/
7170
private MessageBuilderDomainService $messageBuilder;
7271

73-
/**
74-
* 工具文件ID匹配器
75-
*/
76-
private ToolFileIdMatcher $toolFileIdMatcher;
77-
7872
public function __construct(
7973
private readonly WorkspaceDomainService $workspaceDomainService,
8074
private readonly TopicDomainService $topicDomainService,
@@ -91,7 +85,6 @@ public function __construct(
9185
) {
9286
$this->messageBuilder = new MessageBuilderDomainService();
9387
$this->logger = $loggerFactory->get(get_class($this));
94-
$this->toolFileIdMatcher = new ToolFileIdMatcher($this->logger);
9588
}
9689

9790
/**
@@ -690,6 +683,7 @@ private function handleReceivedMessage(TopicTaskMessageDTO $messageDTO, TaskCont
690683
$attachments = $payload->getAttachments() ?? [];
691684
$projectArchive = $payload->getProjectArchive() ?? [];
692685
$showInUi = $payload->getShowInUi() ?? true;
686+
$messageId = $payload->getMessageId();
693687

694688
// 2. 处理未知消息类型
695689
if (! MessageType::isValid($messageType)) {
@@ -711,8 +705,8 @@ private function handleReceivedMessage(TopicTaskMessageDTO $messageDTO, TaskCont
711705
try {
712706
if ($tool !== null && ! empty($tool['attachments'])) {
713707
$this->processToolAttachments($tool, $taskContext);
714-
// 使用工具文件ID匹配器处理各种工具类型
715-
$this->toolFileIdMatcher->matchFileIdForTools($tool);
708+
// 使用工具处理器处理文件ID匹配
709+
ToolProcessor::processToolAttachments($tool);
716710
}
717711

718712
// 处理消息附件
@@ -722,7 +716,11 @@ private function handleReceivedMessage(TopicTaskMessageDTO $messageDTO, TaskCont
722716
if ($status === TaskStatus::Suspended->value) {
723717
$this->pauseTaskSteps($steps);
724718
} elseif ($status === TaskStatus::FINISHED->value) {
725-
$this->getOutputContent($taskContext, $attachments, $tool);
719+
// 使用工具处理器生成输出内容工具
720+
$outputTool = ToolProcessor::generateOutputContentTool($attachments);
721+
if ($outputTool !== null) {
722+
$tool = $outputTool;
723+
}
726724
}
727725

728726
// 4. 记录AI消息
@@ -739,7 +737,8 @@ private function handleReceivedMessage(TopicTaskMessageDTO $messageDTO, TaskCont
739737
$task->getTopicId(),
740738
$event,
741739
$attachments,
742-
$showInUi
740+
$showInUi,
741+
$messageId
743742
);
744743

745744
// 5. 发送消息到客户端
@@ -790,80 +789,6 @@ private function pauseTaskSteps(array &$steps): void
790789
}
791790
}
792791

793-
private function getOutputContent(TaskContext $taskContext, array $attachments, ?array &$tool)
794-
{
795-
if (empty($attachments)) {
796-
return;
797-
}
798-
799-
$file = [];
800-
$htmlFiles = [];
801-
$mdFiles = [];
802-
803-
// 首先将文件按类型分组
804-
foreach ($attachments as $attachment) {
805-
$extension = strtolower($attachment['file_extension'] ?? '');
806-
if ($extension === 'html') {
807-
$htmlFiles[] = $attachment;
808-
} elseif ($extension === 'md') {
809-
$mdFiles[] = $attachment;
810-
}
811-
}
812-
813-
// 优先处理HTML文件
814-
if (! empty($htmlFiles)) {
815-
// 检查是否有包含关键词的HTML文件
816-
$finalHtmlFiles = array_filter($htmlFiles, function ($item) {
817-
$filename = strtolower($item['filename']);
818-
return strpos($filename, 'final') !== false || strpos($filename, 'report') !== false;
819-
});
820-
821-
if (! empty($finalHtmlFiles)) {
822-
// 如果有多个包含关键词的文件,选择最大的
823-
$file = $this->getMaxSizeFile($finalHtmlFiles);
824-
} else {
825-
// 如果没有包含关键词的文件,选择最大的HTML文件
826-
$file = $this->getMaxSizeFile($htmlFiles);
827-
}
828-
}
829-
// 如果没有HTML文件,处理MD文件
830-
elseif (! empty($mdFiles)) {
831-
// 检查是否有包含关键词的MD文件
832-
$finalMdFiles = array_filter($mdFiles, function ($item) {
833-
$filename = strtolower($item['filename']);
834-
return strpos($filename, 'final') !== false || strpos($filename, 'report') !== false;
835-
});
836-
837-
if (! empty($finalMdFiles)) {
838-
// 如果有多个包含关键词的文件,选择最大的
839-
$file = $this->getMaxSizeFile($finalMdFiles);
840-
} else {
841-
// 如果没有包含关键词的文件,选择最大的MD文件
842-
$file = $this->getMaxSizeFile($mdFiles);
843-
}
844-
}
845-
846-
if (! empty($file)) {
847-
$tool = [
848-
'id' => (string) IdGenerator::getSnowId(),
849-
'name' => 'finish_task',
850-
'action' => '已完成结果文件的输出',
851-
'detail' => [
852-
// 如果文件类型是 html 就使用 html , 如果文件类型是 md 就使用 md, 其他为 text
853-
'type' => $file['file_extension'] === 'html' ? 'html' : ($file['file_extension'] === 'md' ? 'md' : 'text'),
854-
'data' => [
855-
'file_name' => $file['filename'],
856-
'content' => '',
857-
'file_id' => $file['file_id'],
858-
],
859-
],
860-
'remark' => '',
861-
'status' => 'finished',
862-
'attachments' => [],
863-
];
864-
}
865-
}
866-
867792
private function sendErrorMessageToClient(int $topicId, string $taskId, string $chatTopicId, string $chatConversationId, string $message): void
868793
{
869794
$this->sendMessageToClient(
@@ -1242,24 +1167,4 @@ private function convertWebSocketMessageToDTO(array $message): TopicTaskMessageD
12421167
// 创建DTO
12431168
return new TopicTaskMessageDTO($metadata, $payload);
12441169
}
1245-
1246-
/**
1247-
* 从文件数组中获取最大尺寸的文件.
1248-
*
1249-
* @param array $files 文件数组
1250-
* @return null|array 最大尺寸的文件,如果数组为空则返回null
1251-
*/
1252-
private function getMaxSizeFile(array $files)
1253-
{
1254-
if (empty($files)) {
1255-
return null;
1256-
}
1257-
1258-
return array_reduce($files, function ($carry, $item) {
1259-
if ($carry === null || (int) ($item['file_size'] ?? 0) > (int) ($carry['file_size'] ?? 0)) {
1260-
return $item;
1261-
}
1262-
return $carry;
1263-
});
1264-
}
12651170
}

0 commit comments

Comments
 (0)