8 "github.com/opencode-ai/opencode/internal/llm/models"
11type MessageRole string
14 Assistant MessageRole = "assistant"
15 User MessageRole = "user"
16 System MessageRole = "system"
17 Tool MessageRole = "tool"
20type FinishReason string
23 FinishReasonEndTurn FinishReason = "end_turn"
24 FinishReasonMaxTokens FinishReason = "max_tokens"
25 FinishReasonToolUse FinishReason = "tool_use"
26 FinishReasonCanceled FinishReason = "canceled"
27 FinishReasonError FinishReason = "error"
28 FinishReasonPermissionDenied FinishReason = "permission_denied"
30 // Should never happen
31 FinishReasonUnknown FinishReason = "unknown"
34type ContentPart interface {
38type ReasoningContent struct {
39 Thinking string `json:"thinking"`
42func (tc ReasoningContent) String() string {
45func (ReasoningContent) isPart() {}
47type TextContent struct {
48 Text string `json:"text"`
51func (tc TextContent) String() string {
55func (TextContent) isPart() {}
57type ImageURLContent struct {
58 URL string `json:"url"`
59 Detail string `json:"detail,omitempty"`
62func (iuc ImageURLContent) String() string {
66func (ImageURLContent) isPart() {}
68type BinaryContent struct {
74func (bc BinaryContent) String(provider models.ModelProvider) string {
75 base64Encoded := base64.StdEncoding.EncodeToString(bc.Data)
76 if provider == models.ProviderOpenAI {
77 return "data:" + bc.MIMEType + ";base64," + base64Encoded
82func (BinaryContent) isPart() {}
86 Name string `json:"name"`
87 Input string `json:"input"`
88 Type string `json:"type"`
89 Finished bool `json:"finished"`
92func (ToolCall) isPart() {}
94type ToolResult struct {
95 ToolCallID string `json:"tool_call_id"`
96 Name string `json:"name"`
97 Content string `json:"content"`
98 Metadata string `json:"metadata"`
99 IsError bool `json:"is_error"`
102func (ToolResult) isPart() {}
105 Reason FinishReason `json:"reason"`
106 Time int64 `json:"time"`
109func (Finish) isPart() {}
121func (m *Message) Content() TextContent {
122 for _, part := range m.Parts {
123 if c, ok := part.(TextContent); ok {
130func (m *Message) ReasoningContent() ReasoningContent {
131 for _, part := range m.Parts {
132 if c, ok := part.(ReasoningContent); ok {
136 return ReasoningContent{}
139func (m *Message) ImageURLContent() []ImageURLContent {
140 imageURLContents := make([]ImageURLContent, 0)
141 for _, part := range m.Parts {
142 if c, ok := part.(ImageURLContent); ok {
143 imageURLContents = append(imageURLContents, c)
146 return imageURLContents
149func (m *Message) BinaryContent() []BinaryContent {
150 binaryContents := make([]BinaryContent, 0)
151 for _, part := range m.Parts {
152 if c, ok := part.(BinaryContent); ok {
153 binaryContents = append(binaryContents, c)
156 return binaryContents
159func (m *Message) ToolCalls() []ToolCall {
160 toolCalls := make([]ToolCall, 0)
161 for _, part := range m.Parts {
162 if c, ok := part.(ToolCall); ok {
163 toolCalls = append(toolCalls, c)
169func (m *Message) ToolResults() []ToolResult {
170 toolResults := make([]ToolResult, 0)
171 for _, part := range m.Parts {
172 if c, ok := part.(ToolResult); ok {
173 toolResults = append(toolResults, c)
179func (m *Message) IsFinished() bool {
180 for _, part := range m.Parts {
181 if _, ok := part.(Finish); ok {
188func (m *Message) FinishPart() *Finish {
189 for _, part := range m.Parts {
190 if c, ok := part.(Finish); ok {
197func (m *Message) FinishReason() FinishReason {
198 for _, part := range m.Parts {
199 if c, ok := part.(Finish); ok {
206func (m *Message) IsThinking() bool {
207 if m.ReasoningContent().Thinking != "" && m.Content().Text == "" && !m.IsFinished() {
213func (m *Message) AppendContent(delta string) {
215 for i, part := range m.Parts {
216 if c, ok := part.(TextContent); ok {
217 m.Parts[i] = TextContent{Text: c.Text + delta}
222 m.Parts = append(m.Parts, TextContent{Text: delta})
226func (m *Message) AppendReasoningContent(delta string) {
228 for i, part := range m.Parts {
229 if c, ok := part.(ReasoningContent); ok {
230 m.Parts[i] = ReasoningContent{Thinking: c.Thinking + delta}
235 m.Parts = append(m.Parts, ReasoningContent{Thinking: delta})
239func (m *Message) FinishToolCall(toolCallID string) {
240 for i, part := range m.Parts {
241 if c, ok := part.(ToolCall); ok {
242 if c.ID == toolCallID {
243 m.Parts[i] = ToolCall{
256func (m *Message) AppendToolCallInput(toolCallID string, inputDelta string) {
257 for i, part := range m.Parts {
258 if c, ok := part.(ToolCall); ok {
259 if c.ID == toolCallID {
260 m.Parts[i] = ToolCall{
263 Input: c.Input + inputDelta,
265 Finished: c.Finished,
273func (m *Message) AddToolCall(tc ToolCall) {
274 for i, part := range m.Parts {
275 if c, ok := part.(ToolCall); ok {
282 m.Parts = append(m.Parts, tc)
285func (m *Message) SetToolCalls(tc []ToolCall) {
286 // remove any existing tool call part it could have multiple
287 parts := make([]ContentPart, 0)
288 for _, part := range m.Parts {
289 if _, ok := part.(ToolCall); ok {
292 parts = append(parts, part)
295 for _, toolCall := range tc {
296 m.Parts = append(m.Parts, toolCall)
300func (m *Message) AddToolResult(tr ToolResult) {
301 m.Parts = append(m.Parts, tr)
304func (m *Message) SetToolResults(tr []ToolResult) {
305 for _, toolResult := range tr {
306 m.Parts = append(m.Parts, toolResult)
310func (m *Message) AddFinish(reason FinishReason) {
311 // remove any existing finish part
312 for i, part := range m.Parts {
313 if _, ok := part.(Finish); ok {
314 m.Parts = slices.Delete(m.Parts, i, i+1)
318 m.Parts = append(m.Parts, Finish{Reason: reason, Time: time.Now().Unix()})
321func (m *Message) AddImageURL(url, detail string) {
322 m.Parts = append(m.Parts, ImageURLContent{URL: url, Detail: detail})
325func (m *Message) AddBinary(mimeType string, data []byte) {
326 m.Parts = append(m.Parts, BinaryContent{MIMEType: mimeType, Data: data})
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list