Files
ars-backend/app/Services/Tool/ToolExecutor.php
ROOG 59d4831f00 main: 增强工具调用与消息流程
- 支持 tool.call 和 tool.result 消息类型处理
- 引入 Tool 调度与执行逻辑,支持超时与结果截断
- 增加 ToolRegistry 和 ToolExecutor 管理工具定义与执行
- 更新上下文构建与消息映射逻辑,适配工具闭环处理
- 扩展配置与环境变量,支持 Tool 调用相关选项
- 增强单元测试覆盖工具调用与执行情景
- 更新文档和 OpenAPI,新增工具相关说明与模型定义
2025-12-22 12:36:59 +08:00

87 lines
2.4 KiB
PHP

<?php
namespace App\Services\Tool;
use Illuminate\Support\Str;
/**
* Tool 执行调度器,负责超时/结果截断等基础防护。
*/
class ToolExecutor
{
public function __construct(
private readonly ToolRegistry $registry,
private ?int $timeoutSeconds = null,
private ?int $maxResultBytes = null,
) {
$this->timeoutSeconds = $this->timeoutSeconds ?? (int) config('agent.tools.timeout_seconds', 15);
$this->maxResultBytes = $this->maxResultBytes ?? (int) config('agent.tools.result_max_bytes', 4096);
}
public function execute(ToolCall $call): ToolResult
{
$tool = $this->registry->get($call->name);
if (! $tool) {
return new ToolResult(
$call->runId,
$call->parentRunId,
$call->toolCallId,
$call->name,
'FAILED',
'',
'TOOL_NOT_FOUND'
);
}
$started = microtime(true);
try {
$result = $tool->execute($call->arguments);
$output = is_string($result) ? $result : json_encode($result, JSON_UNESCAPED_UNICODE);
} catch (\Throwable $exception) {
return new ToolResult(
$call->runId,
$call->parentRunId,
$call->toolCallId,
$call->name,
'FAILED',
'',
Str::limit($exception->getMessage(), 200)
);
}
$duration = microtime(true) - $started;
$truncated = false;
if ($this->maxResultBytes > 0 && strlen($output) > $this->maxResultBytes) {
$output = substr($output, 0, $this->maxResultBytes);
$truncated = true;
}
if ($this->timeoutSeconds > 0 && $duration > $this->timeoutSeconds) {
return new ToolResult(
$call->runId,
$call->parentRunId,
$call->toolCallId,
$call->name,
'TIMEOUT',
$output,
'TOOL_TIMEOUT',
$truncated
);
}
return new ToolResult(
$call->runId,
$call->parentRunId,
$call->toolCallId,
$call->name,
'SUCCESS',
$output,
null,
$truncated
);
}
}