跳转到主要内容

权限请求

默认行为(deny-all

config/copilot.phppermission_approve"deny-all"(默认)时,Copilot::run()Copilot::start() 中的权限请求会被自动 拒绝 由于以文本生成为主的用途通常不需要权限,因此这是一个安全的默认值。
// config/copilot.php
'permission_approve' => env('COPILOT_PERMISSION_APPROVE', 'deny-all'),

可配置的值

行为
"deny-all"全部自动拒绝(默认
"approve-safety"只拒绝 shellwrite,其他自动许可
"approve-all"全部自动许可
false无处理器。onPermissionRequest 是必需的(与官方 SDK 相同)
// .env
COPILOT_PERMISSION_APPROVE="approve-safety"
如果接收用户输入的 prompt,"approve-safety""approve-all" 是危险的。 请务必使用 false"deny-all"。 即使是 read-only 权限,Laravel 项目的代码也可能被读取。

PermissionHandler::approveAll()

PermissionHandler::approveAll() 会自动许可所有请求。
use Revolution\Copilot\Facades\Copilot;
use Revolution\Copilot\Support\PermissionHandler;
use Revolution\Copilot\Types\SessionConfig;

$config = new SessionConfig(
    onPermissionRequest: PermissionHandler::approveAll(),
);

$response = Copilot::run(prompt: 'Hello', config: $config);

PermissionHandler::approveSafety()

PermissionHandler::approveSafety() 只拒绝高风险的权限(shellwrite),其他自动许可。
use Revolution\Copilot\Facades\Copilot;
use Revolution\Copilot\Support\PermissionHandler;
use Revolution\Copilot\Types\SessionConfig;

$config = new SessionConfig(
    onPermissionRequest: PermissionHandler::approveSafety(),
);

$response = Copilot::run(prompt: 'Hello', config: $config);
即便如此也未必完全安全。 若要严格控制,请实现自定义处理器,通过查看 $request['kind'] 进行判断。

PermissionHandler::denyAll()

PermissionHandler::denyAll() 会拒绝所有请求。
use Revolution\Copilot\Support\PermissionHandler;
use Revolution\Copilot\Types\SessionConfig;

$config = new SessionConfig(
    onPermissionRequest: PermissionHandler::denyAll(),
);

直接使用 Client 的情况

直接使用 CopilotClient 时,与官方 SDK 一样,onPermissionRequest必需的
use Revolution\Copilot\Client;
use Revolution\Copilot\Support\PermissionHandler;

$client = new Client([
    'cli_path' => 'copilot',
    'cli_args' => [],
    'cwd' => base_path(),
    'log_level' => 'info',
    'env' => null,
]);
$client->start();

// onPermissionRequest 是必需的
$session = $client->createSession([
    'onPermissionRequest' => PermissionHandler::approveSafety(),
]);

// 省略会抛出 InvalidArgumentException
// $session = $client->createSession([]); // Error!

自定义处理器

要按请求类型控制许可 / 拒绝,请传入闭包。 $request$invocation 是如下的数组。
use Illuminate\Support\Facades\Artisan;
use Revolution\Copilot\Contracts\CopilotSession;
use Revolution\Copilot\Facades\Copilot;
use Revolution\Copilot\Support\PermissionRequestResultKind;
use Revolution\Copilot\Types\SessionConfig;

use function Laravel\Prompts\{confirm, note, spin, text};

Artisan::command('copilot:chat', function () {
    $config = new SessionConfig(
        onPermissionRequest: function (array $request, array $invocation) {
            $confirm = confirm(
                label: 'Do you accept the requested permissions?',
            );
            if ($confirm) {
                return PermissionRequestResultKind::approveOnce();
            } else {
                return PermissionRequestResultKind::reject();
            }
        },
    );

    Copilot::start(function (CopilotSession $session) use ($config) {
        while (true) {
            $prompt = text(
                label: 'Enter your prompt',
                placeholder: 'Ask me anything...',
                required: true,
                hint: 'Ctrl+C to exit',
            );

            $response = spin(
                callback: fn () => $session->sendAndWait($prompt),
                message: 'Waiting for Copilot response...',
            );

            note($response->content());
        }
    }, config: $config);
});

$request

kindtoolCallId 以外的字段会因 kind 而变化。
kind: "shell" | "write" | "mcp" | "read" | "url" | "custom-tool" | "memory" | "hook"
[
  "kind" => "shell",
  "toolCallId" => "toolu_...",
  "fullCommandText" => "...",
  "intention" => "Run copilot:ping to test permission request",
  "commands" => [
    [
      "identifier" => "bash",
      "readOnly" => false,
    ]
  ]
  "possiblePaths" => [],
  "possibleUrls" => [],
  "hasWriteFileRedirection" => false,
  "canOfferSessionApproval" => false,
]

$invocation

[
  "sessionId" => "...",
]

Response

权限判断结果以数组形式返回。 使用 PermissionRequestResultKind 类可以更易读。
return PermissionRequestResultKind::approveOnce();
return PermissionRequestResultKind::reject();

协议详情

在 Protocol v3(当前默认)中,权限请求不再作为 JSON-RPC 请求,而是作为会话事件(permission.requested)投递。 SDK 内部会处理它,并通过 session.permissions.handlePendingPermissionRequest RPC 进行响应。 SessionConfig 的使用方式不变。 只要向 onPermissionRequest 传入处理器,协议差异会由 SDK 吸收。

PermissionRequestResultKind

你也可以直接以 ['kind' => 'approve-once'] 的形式返回,但使用 PermissionRequestResultKind 会更直观。
use Revolution\Copilot\Support\PermissionRequestResultKind;

$confirm = confirm(
    label: 'Do you accept the requested permissions?',
);

if ($confirm) {
    return PermissionRequestResultKind::approveOnce();
} else {
    return PermissionRequestResultKind::reject();
}

可用的方法

方法说明
approveOnce()approve-once仅本次请求许可
approveForSession()approve-for-session在本会话内全部许可同类请求
approveForLocation()approve-for-location从该位置(文件路径等)发起的所有同类请求都许可
reject()reject拒绝请求
userNotAvailable()user-not-available用户无法响应的状态(如非交互环境)
noResult()no-result当处理器无法返回结果时(跳过 RPC 调用)
如果想使用 Laravel\Prompts\select,可以通过 PermissionRequestResultKind::select() 获取选项。
use Revolution\Copilot\Support\PermissionRequestResultKind;
use function Laravel\Prompts\select;

$select = select(
    label: 'Do you accept the requested permissions?',
    options: PermissionRequestResultKind::select(),
);

return ['kind' => $select];

no-result

当处理器无法返回结果时(例如非交互环境),可以返回 no-result。 返回 no-result 会跳过 RPC 调用,采用 Copilot CLI 侧的默认拒绝。
return PermissionRequestResultKind::noResult();
// 或 ['kind' => 'no-result']
最新信息请参考 GitHub 仓库
最后修改于 2026年7月13日