• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

eliashaeussler / typo3-solver / 13279972588

12 Feb 2025 07:10AM UTC coverage: 81.987% (-6.0%) from 88.036%
13279972588

Pull #295

github

web-flow
Merge da0f95ebf into 2764f6ab2
Pull Request #295: [FEATURE] Add Gemini as additional solution provider

4 of 85 new or added lines in 7 files covered. (4.71%)

1 existing line in 1 file now uncovered.

883 of 1077 relevant lines covered (81.99%)

2.17 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

78.72
/Classes/ProblemSolving/Solution/Model/CompletionResponse.php
1
<?php
2

3
declare(strict_types=1);
4

5
/*
6
 * This file is part of the TYPO3 CMS extension "solver".
7
 *
8
 * Copyright (C) 2023-2025 Elias Häußler <elias@haeussler.dev>
9
 *
10
 * This program is free software: you can redistribute it and/or modify
11
 * it under the terms of the GNU General Public License as published by
12
 * the Free Software Foundation, either version 2 of the License, or
13
 * (at your option) any later version.
14
 *
15
 * This program is distributed in the hope that it will be useful,
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
 * GNU General Public License for more details.
19
 *
20
 * You should have received a copy of the GNU General Public License
21
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
22
 */
23

24
namespace EliasHaeussler\Typo3Solver\ProblemSolving\Solution\Model;
25

26
use GeminiAPI\Enums;
27
use GeminiAPI\Resources;
28
use OpenAI\Responses;
29

30
/**
31
 * CompletionResponse
32
 *
33
 * @author Elias Häußler <elias@haeussler.dev>
34
 * @license GPL-2.0-or-later
35
 *
36
 * @phpstan-import-type MessageArray from Message
37
 * @phpstan-type CompletionResponseArray array{index: int, message: MessageArray, finishReason: string|null}
38
 */
39
final class CompletionResponse implements \JsonSerializable
40
{
41
    public function __construct(
7✔
42
        public readonly int $index,
43
        public readonly Message $message,
44
        public readonly ?string $finishReason = null,
45
    ) {}
7✔
46

47
    public static function fromOpenAIChoice(
2✔
48
        Responses\Chat\CreateResponseChoice|Responses\Chat\CreateStreamedResponseChoice $choice,
49
    ): self {
50
        if ($choice instanceof Responses\Chat\CreateStreamedResponseChoice) {
2✔
51
            $role = (string)$choice->delta->role;
1✔
52
            $content = $choice->delta->content;
1✔
53
        } else {
54
            $role = $choice->message->role;
1✔
55
            $content = $choice->message->content;
1✔
56
        }
57

58
        return new self($choice->index, new Message($role, $content), $choice->finishReason);
2✔
59
    }
60

NEW
61
    public static function fromGeminiCandidate(Resources\Candidate $candidate): self
×
62
    {
NEW
63
        $contentPart = \reset($candidate->content->parts);
×
64

NEW
65
        if ($contentPart instanceof Resources\Parts\TextPart) {
×
NEW
66
            $content = $contentPart->text;
×
67
        } else {
NEW
68
            $content = null;
×
69
        }
70

NEW
71
        return new self(
×
NEW
72
            $candidate->index,
×
NEW
73
            new Message(Enums\Role::Model->value, $content),
×
NEW
74
            $candidate->finishReason->value,
×
NEW
75
        );
×
76
    }
77

78
    /**
79
     * @param array{index?: int, message?: array{role?: string, content?: string|null}, finishReason?: string|null} $response
80
     */
81
    public static function fromArray(array $response): self
1✔
82
    {
83
        $message = $response['message'] ?? [];
1✔
84
        $message['role'] ??= '';
1✔
85
        $message['content'] ??= null;
1✔
86

87
        return new self(
1✔
88
            $response['index'] ?? 0,
1✔
89
            new Message($message['role'], $message['content']),
1✔
90
            $response['finishReason'] ?? null,
1✔
91
        );
1✔
92
    }
93

94
    public function merge(self $other): self
1✔
95
    {
96
        return new self(
1✔
97
            $this->index,
1✔
98
            new Message(
1✔
99
                $other->message->role,
1✔
100
                $this->message->content . $other->message->content,
1✔
101
            ),
1✔
102
            $other->finishReason,
1✔
103
        );
1✔
104
    }
105

106
    public function isFinished(): bool
1✔
107
    {
108
        return $this->finishReason !== null;
1✔
109
    }
110

111
    /**
112
     * @return CompletionResponseArray
113
     */
114
    public function toArray(): array
2✔
115
    {
116
        return [
2✔
117
            'index' => $this->index,
2✔
118
            'message' => $this->message->toArray(),
2✔
119
            'finishReason' => $this->finishReason,
2✔
120
        ];
2✔
121
    }
122

123
    /**
124
     * @return CompletionResponseArray
125
     */
126
    public function jsonSerialize(): array
1✔
127
    {
128
        return $this->toArray();
1✔
129
    }
130
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc