first commit
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\SystemAgent\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Modules\AnnoRoute\Attribute\GetRoute;
|
||||
use Modules\AnnoRoute\Attribute\PutRoute;
|
||||
use Modules\AnnoRoute\Attribute\RequestAttribute;
|
||||
use Modules\Common\Http\Controllers\BaseController;
|
||||
use Modules\SystemAgent\Models\AgentModel;
|
||||
|
||||
#[RequestAttribute('/ai/agent', 'ai.agent')]
|
||||
class AgentController extends BaseController
|
||||
{
|
||||
#[GetRoute(authorize: 'query')]
|
||||
public function query(): JsonResponse
|
||||
{
|
||||
$agents = AgentModel::orderBy('id')->get();
|
||||
return $this->success($agents->toArray());
|
||||
}
|
||||
|
||||
#[GetRoute('/{id}', authorize: 'query', where: ['id' => '[0-9]+'])]
|
||||
public function show(int $id): JsonResponse
|
||||
{
|
||||
$agent = AgentModel::find($id);
|
||||
if (! $agent) {
|
||||
return $this->error('Agent not found');
|
||||
}
|
||||
return $this->success($agent->toArray());
|
||||
}
|
||||
|
||||
#[PutRoute('/{id}', authorize: 'update', where: ['id' => '[0-9]+'])]
|
||||
public function update(int $id, Request $request): JsonResponse
|
||||
{
|
||||
$enabled = $request->boolean('enabled', true);
|
||||
$model = AgentModel::find($id);
|
||||
if (! $model) {
|
||||
return $this->error('Agent not found');
|
||||
}
|
||||
$model->enabled = $enabled;
|
||||
$model->save();
|
||||
return $this->success();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\SystemAgent\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Laravel\Ai\Responses\StreamableAgentResponse;
|
||||
use Modules\AnnoRoute\Attribute\DeleteRoute;
|
||||
use Modules\AnnoRoute\Attribute\GetRoute;
|
||||
use Modules\AnnoRoute\Attribute\PostRoute;
|
||||
use Modules\AnnoRoute\Attribute\RequestAttribute;
|
||||
use Modules\Common\Http\Controllers\BaseController;
|
||||
use Modules\SystemAgent\Ai\Agents\XinChatAgent;
|
||||
use Modules\SystemAgent\Models\AgentModel;
|
||||
|
||||
#[RequestAttribute('/ai/chat', 'ai.chat')]
|
||||
class ChatController extends BaseController
|
||||
{
|
||||
/**
|
||||
* 发送消息并返回 SSE 流式响应
|
||||
*/
|
||||
#[PostRoute('/send', 'send')]
|
||||
public function send(Request $request): StreamableAgentResponse|JsonResponse
|
||||
{
|
||||
$request->validate([
|
||||
'message' => 'required|string|max:10000',
|
||||
'conversation_id' => 'nullable|string|max:36',
|
||||
'agent_id' => 'nullable|integer|exists:agents,id',
|
||||
]);
|
||||
|
||||
$message = $request->input('message');
|
||||
$conversationId = $request->input('conversation_id');
|
||||
$agentId = $request->input('agent_id');
|
||||
$user = $request->user();
|
||||
|
||||
try {
|
||||
if ($agentId) {
|
||||
$agentModel = AgentModel::findOrFail($agentId);
|
||||
$agentClass = $agentModel->namespace;
|
||||
$agent = $agentClass::make();
|
||||
} else {
|
||||
$agent = XinChatAgent::make();
|
||||
}
|
||||
|
||||
if ($conversationId) {
|
||||
// 继续已有会话
|
||||
$response = $agent
|
||||
->continue($conversationId, as: $user)
|
||||
->stream($message);
|
||||
} else {
|
||||
// 新建会话
|
||||
$response = $agent
|
||||
->forUser($user)
|
||||
->stream($message);
|
||||
}
|
||||
|
||||
return $response;
|
||||
} catch (\Throwable $e) {
|
||||
return $this->error('AI 响应失败:' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前用户的会话列表
|
||||
*/
|
||||
#[GetRoute('/conversations', 'conversations')]
|
||||
public function conversations(Request $request): JsonResponse
|
||||
{
|
||||
$user = $request->user();
|
||||
|
||||
$conversations = $user->conversations()
|
||||
->latest('updated_at')
|
||||
->get()
|
||||
->map(fn ($conversation) => [
|
||||
'key' => $conversation->id,
|
||||
'label' => $conversation->title,
|
||||
'updated_at' => $conversation->updated_at->toISOString(),
|
||||
]);
|
||||
|
||||
return $this->success($conversations->toArray());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定会话的消息列表
|
||||
*/
|
||||
#[GetRoute('/messages/{conversationId}', 'messages')]
|
||||
public function messages(Request $request, string $conversationId): JsonResponse
|
||||
{
|
||||
$user = $request->user();
|
||||
|
||||
$conversation = $user->conversations()->find($conversationId);
|
||||
|
||||
if (! $conversation) {
|
||||
return $this->error('会话不存在');
|
||||
}
|
||||
|
||||
$messages = $conversation->messages()
|
||||
->oldest()
|
||||
->get()
|
||||
->map(fn ($msg) => [
|
||||
'key' => $msg->id,
|
||||
'role' => $msg->role,
|
||||
'content' => $msg->content,
|
||||
'created_at' => $msg->created_at->toISOString(),
|
||||
]);
|
||||
|
||||
return $this->success($messages->toArray());
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除指定会话
|
||||
*/
|
||||
#[DeleteRoute('/messages/{conversationId}', 'delete')]
|
||||
public function deleteConversation(Request $request, string $conversationId): JsonResponse
|
||||
{
|
||||
$user = $request->user();
|
||||
|
||||
$conversation = $user->conversations()->find($conversationId);
|
||||
|
||||
if (! $conversation) {
|
||||
return $this->error('会话不存在');
|
||||
}
|
||||
|
||||
$conversation->delete();
|
||||
|
||||
return $this->success('会话已删除');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\SystemAgent\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Laravel\Ai\Models\Conversation;
|
||||
use Modules\AnnoRoute\Attribute\DeleteRoute;
|
||||
use Modules\AnnoRoute\Attribute\GetRoute;
|
||||
use Modules\AnnoRoute\Attribute\RequestAttribute;
|
||||
use Modules\Common\Http\Controllers\BaseController;
|
||||
use Modules\SystemUser\Models\SysUserModel;
|
||||
|
||||
#[RequestAttribute('/ai/conversation', 'ai.conversation')]
|
||||
class ConversationController extends BaseController
|
||||
{
|
||||
protected array $searchField = [
|
||||
'title' => 'like',
|
||||
];
|
||||
|
||||
protected array $quickSearchField = ['title'];
|
||||
|
||||
/**
|
||||
* 会话列表
|
||||
*/
|
||||
#[GetRoute(authorize: 'query')]
|
||||
public function query(Request $request): JsonResponse
|
||||
{
|
||||
$params = $request->all();
|
||||
$perPage = (int) ($params['pageSize'] ?? 10);
|
||||
$query = Conversation::query()->withCount('messages');
|
||||
|
||||
$data = $this->buildSearch($params, $query)
|
||||
->orderBy('updated_at', 'desc')
|
||||
->paginate($perPage);
|
||||
|
||||
$userIds = $data->pluck('user_id')->filter()->unique();
|
||||
$users = SysUserModel::whereIn('id', $userIds)->pluck('username', 'id');
|
||||
|
||||
$data = $data->through(function ($conversation) use ($users) {
|
||||
return [
|
||||
'id' => $conversation->id,
|
||||
'user_id' => $conversation->user_id,
|
||||
'username' => $users[$conversation->user_id] ?? '',
|
||||
'title' => $conversation->title,
|
||||
'message_count' => $conversation->messages_count,
|
||||
'created_at' => $conversation->created_at?->toISOString(),
|
||||
'updated_at' => $conversation->updated_at?->toISOString(),
|
||||
];
|
||||
});
|
||||
|
||||
return $this->success($data->toArray());
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除会话
|
||||
*/
|
||||
#[DeleteRoute(route: '/{id}', authorize: 'delete', where: ['id' => '[a-zA-Z0-9\-]+'])]
|
||||
public function delete(string $id): JsonResponse
|
||||
{
|
||||
$conversation = Conversation::find($id);
|
||||
|
||||
if (! $conversation) {
|
||||
return $this->error('会话不存在');
|
||||
}
|
||||
|
||||
$conversation->delete();
|
||||
|
||||
return $this->success('会话已删除');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取会话消息列表
|
||||
*/
|
||||
#[GetRoute('/{id}/messages', authorize: 'query', where: ['id' => '[a-zA-Z0-9\-]+'])]
|
||||
public function messages(string $id, Request $request): JsonResponse
|
||||
{
|
||||
$conversation = Conversation::find($id);
|
||||
|
||||
if (! $conversation) {
|
||||
return $this->error('会话不存在');
|
||||
}
|
||||
|
||||
$perPage = (int) $request->input('pageSize', 20);
|
||||
$data = $conversation->messages()
|
||||
->orderBy('created_at')
|
||||
->paginate($perPage)
|
||||
->toArray();
|
||||
|
||||
return $this->success($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取会话详情
|
||||
*/
|
||||
#[GetRoute('/{id}', authorize: 'query', where: ['id' => '[a-zA-Z0-9\-]+'])]
|
||||
public function show(string $id): JsonResponse
|
||||
{
|
||||
$conversation = Conversation::withCount('messages')->find($id);
|
||||
|
||||
if (! $conversation) {
|
||||
return $this->error('会话不存在');
|
||||
}
|
||||
|
||||
$user = $conversation->user_id
|
||||
? SysUserModel::find($conversation->user_id)
|
||||
: null;
|
||||
|
||||
return $this->success([
|
||||
'id' => $conversation->id,
|
||||
'user_id' => $conversation->user_id,
|
||||
'username' => $user?->username ?? '',
|
||||
'title' => $conversation->title,
|
||||
'message_count' => $conversation->messages_count,
|
||||
'created_at' => $conversation->created_at?->toISOString(),
|
||||
'updated_at' => $conversation->updated_at?->toISOString(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user