diff --git a/src/Contracts/CopilotSession.php b/src/Contracts/CopilotSession.php index 105c395..46c2b19 100644 --- a/src/Contracts/CopilotSession.php +++ b/src/Contracts/CopilotSession.php @@ -6,6 +6,7 @@ use Closure; use Revolution\Copilot\Enums\SessionEventType; +use Revolution\Copilot\Exceptions\JsonRpcException; use Revolution\Copilot\Rpc\SessionRpc; use Revolution\Copilot\Types\SessionEvent; @@ -24,6 +25,13 @@ public function id(): string; */ public function rpc(): SessionRpc; + /** + * Switch the model for this session. + * + * @throws JsonRpcException + */ + public function setModel(string $modelId): void; + /** * Send a message to this session. */ diff --git a/src/Session.php b/src/Session.php index d83b847..a2be70e 100644 --- a/src/Session.php +++ b/src/Session.php @@ -20,6 +20,7 @@ use Revolution\Copilot\JsonRpc\JsonRpcClient; use Revolution\Copilot\Rpc\SessionRpc; use Revolution\Copilot\Support\PermissionRequestKind; +use Revolution\Copilot\Types\Rpc\SessionModelSwitchToParams; use Revolution\Copilot\Types\SessionEvent; use Revolution\Copilot\Types\SessionHooks; use Revolution\Copilot\Types\UserInputRequest; @@ -662,6 +663,16 @@ public function destroy(): void $this->hooks = null; } + /** + * Switch the model for this session. + * + * @throws JsonRpcException + */ + public function setModel(string $modelId): void + { + $this->rpc()->model()->switchTo(new SessionModelSwitchToParams(modelId: $modelId)); + } + /** * Abort the currently processing message. * diff --git a/src/Testing/FakeSession.php b/src/Testing/FakeSession.php index 8ca4089..8ab9fa5 100644 --- a/src/Testing/FakeSession.php +++ b/src/Testing/FakeSession.php @@ -47,6 +47,11 @@ public function rpc(): SessionRpc ); } + public function setModel(string $modelId): void + { + // No-op in fake + } + public function send(string $prompt, ?array $attachments = null, ?string $mode = null): string { $this->recorded[] = [ diff --git a/tests/Feature/SessionTest.php b/tests/Feature/SessionTest.php index dfef73d..4b20a84 100644 --- a/tests/Feature/SessionTest.php +++ b/tests/Feature/SessionTest.php @@ -299,6 +299,20 @@ $session->abort(); }); + it('setModel calls session.model.switchTo via rpc', function () { + $mockClient = Mockery::mock(JsonRpcClient::class); + $mockClient->shouldReceive('request') + ->with('session.model.switchTo', [ + 'modelId' => 'claude-sonnet-4', + 'sessionId' => 'test-session', + ]) + ->once() + ->andReturn(['modelId' => 'claude-sonnet-4']); + + $session = new Session('test-session', $mockClient); + $session->setModel('claude-sonnet-4'); + }); + it('handlePermissionRequest uses registered handler', function () { $mockClient = Mockery::mock(JsonRpcClient::class); $session = new Session('test-session', $mockClient);