diff options
| author | Dax <[email protected]> | 2025-07-07 15:53:43 -0400 |
|---|---|---|
| committer | GitHub <[email protected]> | 2025-07-07 15:53:43 -0400 |
| commit | f884766445bbf1fbce11f1db4bc6174e72d9baa5 (patch) | |
| tree | e7d9e7b3d8efc8bed249f9d29e2d8fb838a275f2 /packages/tui | |
| parent | 76b2e4539cb97bae5812ed2d832ce49d02e70c64 (diff) | |
| download | opencode-f884766445bbf1fbce11f1db4bc6174e72d9baa5.tar.gz opencode-f884766445bbf1fbce11f1db4bc6174e72d9baa5.zip | |
v2 message format and upgrade to ai sdk v5 (#743)
Co-authored-by: GitHub Action <[email protected]>
Co-authored-by: Liang-Shih Lin <[email protected]>
Co-authored-by: Dominik Engelhardt <[email protected]>
Co-authored-by: Jay V <[email protected]>
Co-authored-by: adamdottv <[email protected]>
Diffstat (limited to 'packages/tui')
| -rw-r--r-- | packages/tui/go.mod | 2 | ||||
| -rw-r--r-- | packages/tui/internal/app/app.go | 51 | ||||
| -rw-r--r-- | packages/tui/internal/components/chat/editor.go | 8 | ||||
| -rw-r--r-- | packages/tui/internal/components/chat/message.go | 324 | ||||
| -rw-r--r-- | packages/tui/internal/components/chat/messages.go | 66 | ||||
| -rw-r--r-- | packages/tui/internal/components/status/status.go | 25 | ||||
| -rw-r--r-- | packages/tui/internal/tui/tui.go | 39 | ||||
| -rw-r--r-- | packages/tui/sdk/.github/workflows/ci.yml | 14 | ||||
| -rw-r--r-- | packages/tui/sdk/.release-please-manifest.json | 2 | ||||
| -rw-r--r-- | packages/tui/sdk/.stats.yml | 6 | ||||
| -rw-r--r-- | packages/tui/sdk/CHANGELOG.md | 25 | ||||
| -rw-r--r-- | packages/tui/sdk/api.md | 27 | ||||
| -rw-r--r-- | packages/tui/sdk/event.go | 120 | ||||
| -rw-r--r-- | packages/tui/sdk/release-please-config.json | 7 | ||||
| -rw-r--r-- | packages/tui/sdk/session.go | 1355 | ||||
| -rw-r--r-- | packages/tui/sdk/session_test.go | 2 | ||||
| -rw-r--r-- | packages/tui/sdk/shared/shared.go | 4 |
17 files changed, 1055 insertions, 1022 deletions
diff --git a/packages/tui/go.mod b/packages/tui/go.mod index 74047af16..90d2af4b1 100644 --- a/packages/tui/go.mod +++ b/packages/tui/go.mod @@ -10,6 +10,7 @@ require ( github.com/charmbracelet/glamour v0.10.0 github.com/charmbracelet/lipgloss/v2 v2.0.0-beta.1 github.com/charmbracelet/x/ansi v0.8.0 + github.com/google/uuid v1.6.0 github.com/lithammer/fuzzysearch v1.1.8 github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 github.com/muesli/reflow v0.3.0 @@ -37,7 +38,6 @@ require ( github.com/go-openapi/jsonpointer v0.21.0 // indirect github.com/go-openapi/swag v0.23.0 // indirect github.com/goccy/go-yaml v1.17.1 // indirect - github.com/google/uuid v1.6.0 // indirect github.com/invopop/yaml v0.3.1 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/mailru/easyjson v0.7.7 // indirect diff --git a/packages/tui/internal/app/app.go b/packages/tui/internal/app/app.go index 469857ab0..cffd07391 100644 --- a/packages/tui/internal/app/app.go +++ b/packages/tui/internal/app/app.go @@ -30,7 +30,7 @@ type App struct { Provider *opencode.Provider Model *opencode.Model Session *opencode.Session - Messages []opencode.Message + Messages []opencode.MessageUnion Commands commands.CommandRegistry } @@ -47,7 +47,7 @@ type SendMsg struct { Attachments []opencode.FilePartParam } type OptimisticMessageAddedMsg struct { - Message opencode.Message + Message opencode.MessageUnion } type FileRenderedMsg struct { FilePath string @@ -116,7 +116,7 @@ func New( State: appState, Client: httpClient, Session: &opencode.Session{}, - Messages: []opencode.Message{}, + Messages: []opencode.MessageUnion{}, Commands: commands.LoadFromConfig(configInfo), } @@ -223,7 +223,10 @@ func (a *App) IsBusy() bool { } lastMessage := a.Messages[len(a.Messages)-1] - return lastMessage.Metadata.Time.Completed == 0 + if casted, ok := lastMessage.(opencode.AssistantMessage); ok { + return casted.Time.Completed == 0 + } + return false } func (a *App) SaveState() { @@ -304,30 +307,28 @@ func (a *App) SendChatMessage( cmds = append(cmds, util.CmdHandler(SessionSelectedMsg(session))) } - optimisticParts := []opencode.MessagePart{{ - Type: opencode.MessagePartTypeText, + optimisticParts := []opencode.UserMessagePart{{ + Type: opencode.UserMessagePartTypeText, Text: text, }} if len(attachments) > 0 { for _, attachment := range attachments { - optimisticParts = append(optimisticParts, opencode.MessagePart{ - Type: opencode.MessagePartTypeFile, - Filename: attachment.Filename.Value, - MediaType: attachment.MediaType.Value, - URL: attachment.URL.Value, + optimisticParts = append(optimisticParts, opencode.UserMessagePart{ + Type: opencode.UserMessagePartTypeFile, + Filename: attachment.Filename.Value, + Mime: attachment.Mime.Value, + URL: attachment.URL.Value, }) } } - optimisticMessage := opencode.Message{ - ID: fmt.Sprintf("optimistic-%d", time.Now().UnixNano()), - Role: opencode.MessageRoleUser, - Parts: optimisticParts, - Metadata: opencode.MessageMetadata{ - SessionID: a.Session.ID, - Time: opencode.MessageMetadataTime{ - Created: float64(time.Now().Unix()), - }, + optimisticMessage := opencode.UserMessage{ + ID: fmt.Sprintf("optimistic-%d", time.Now().UnixNano()), + Role: opencode.UserMessageRoleUser, + Parts: optimisticParts, + SessionID: a.Session.ID, + Time: opencode.UserMessageTime{ + Created: float64(time.Now().Unix()), }, } @@ -335,7 +336,7 @@ func (a *App) SendChatMessage( cmds = append(cmds, util.CmdHandler(OptimisticMessageAddedMsg{Message: optimisticMessage})) cmds = append(cmds, func() tea.Msg { - parts := []opencode.MessagePartUnionParam{ + parts := []opencode.UserMessagePartUnionParam{ opencode.TextPartParam{ Type: opencode.F(opencode.TextPartTypeText), Text: opencode.F(text), @@ -344,10 +345,10 @@ func (a *App) SendChatMessage( if len(attachments) > 0 { for _, attachment := range attachments { parts = append(parts, opencode.FilePartParam{ - MediaType: attachment.MediaType, - Type: attachment.Type, - URL: attachment.URL, - Filename: attachment.Filename, + Mime: attachment.Mime, + Type: attachment.Type, + URL: attachment.URL, + Filename: attachment.Filename, }) } } diff --git a/packages/tui/internal/components/chat/editor.go b/packages/tui/internal/components/chat/editor.go index 9466d541c..5aa05bd1c 100644 --- a/packages/tui/internal/components/chat/editor.go +++ b/packages/tui/internal/components/chat/editor.go @@ -248,10 +248,10 @@ func (m *editorComponent) Submit() (tea.Model, tea.Cmd) { fileParts := make([]opencode.FilePartParam, 0) for _, attachment := range attachments { fileParts = append(fileParts, opencode.FilePartParam{ - Type: opencode.F(opencode.FilePartTypeFile), - MediaType: opencode.F(attachment.MediaType), - URL: opencode.F(attachment.URL), - Filename: opencode.F(attachment.Filename), + Type: opencode.F(opencode.FilePartTypeFile), + Mime: opencode.F(attachment.MediaType), + URL: opencode.F(attachment.URL), + Filename: opencode.F(attachment.Filename), }) } diff --git a/packages/tui/internal/components/chat/message.go b/packages/tui/internal/components/chat/message.go index 9e245c8b2..3414a77d5 100644 --- a/packages/tui/internal/components/chat/message.go +++ b/packages/tui/internal/components/chat/message.go @@ -17,7 +17,6 @@ import ( "github.com/sst/opencode/internal/styles" "github.com/sst/opencode/internal/theme" "github.com/sst/opencode/internal/util" - "github.com/tidwall/gjson" "golang.org/x/text/cases" "golang.org/x/text/language" ) @@ -217,51 +216,50 @@ func renderContentBlock( func renderText( app *app.App, - message opencode.Message, + message opencode.MessageUnion, text string, author string, showToolDetails bool, highlight bool, width int, extra string, - toolCalls ...opencode.ToolInvocationPart, + toolCalls ...opencode.ToolPart, ) string { t := theme.CurrentTheme() - timestamp := time.UnixMilli(int64(message.Metadata.Time.Created)). - Local(). - Format("02 Jan 2006 03:04 PM") - if time.Now().Format("02 Jan 2006") == timestamp[:11] { - // don't show the date if it's today - timestamp = timestamp[12:] - } - info := fmt.Sprintf("%s (%s)", author, timestamp) - info = styles.NewStyle().Foreground(t.TextMuted()).Render(info) - + var ts time.Time backgroundColor := t.BackgroundPanel() if highlight { backgroundColor = t.BackgroundElement() } messageStyle := styles.NewStyle().Background(backgroundColor) - if message.Role == opencode.MessageRoleUser { + content := messageStyle.Render(text) + + switch casted := message.(type) { + case opencode.AssistantMessage: + ts = time.UnixMilli(int64(casted.Time.Created)) + content = util.ToMarkdown(text, width, backgroundColor) + case opencode.UserMessage: + ts = time.UnixMilli(int64(casted.Time.Created)) messageStyle = messageStyle.Width(width - 6) } - content := messageStyle.Render(text) - if message.Role == opencode.MessageRoleAssistant { - content = util.ToMarkdown(text, width, backgroundColor) + timestamp := ts. + Local(). + Format("02 Jan 2006 03:04 PM") + if time.Now().Format("02 Jan 2006") == timestamp[:11] { + // don't show the date if it's today + timestamp = timestamp[12:] } + info := fmt.Sprintf("%s (%s)", author, timestamp) + info = styles.NewStyle().Foreground(t.TextMuted()).Render(info) if !showToolDetails && toolCalls != nil && len(toolCalls) > 0 { content = content + "\n\n" for _, toolCall := range toolCalls { - title := renderToolTitle(toolCall, message.Metadata, width) - metadata := opencode.MessageMetadataTool{} - if _, ok := message.Metadata.Tool[toolCall.ToolInvocation.ToolCallID]; ok { - metadata = message.Metadata.Tool[toolCall.ToolInvocation.ToolCallID] - } + title := renderToolTitle(toolCall, width) style := styles.NewStyle() - if _, ok := metadata.ExtraFields["error"]; ok { + if toolCall.State.Status == opencode.ToolPartStateStatusError { style = style.Foreground(t.Error()) } title = style.Render(title) @@ -276,8 +274,8 @@ func renderText( } content = strings.Join(sections, "\n") - switch message.Role { - case opencode.MessageRoleUser: + switch message.(type) { + case opencode.UserMessage: return renderContentBlock( app, content, @@ -286,7 +284,7 @@ func renderText( WithTextColor(t.Text()), WithBorderColorRight(t.Secondary()), ) - case opencode.MessageRoleAssistant: + case opencode.AssistantMessage: return renderContentBlock( app, content, @@ -300,39 +298,32 @@ func renderText( func renderToolDetails( app *app.App, - toolCall opencode.ToolInvocationPart, - messageMetadata opencode.MessageMetadata, + toolCall opencode.ToolPart, highlight bool, width int, ) string { ignoredTools := []string{"todoread"} - if slices.Contains(ignoredTools, toolCall.ToolInvocation.ToolName) { + if slices.Contains(ignoredTools, toolCall.Tool) { return "" } - toolCallID := toolCall.ToolInvocation.ToolCallID - metadata := opencode.MessageMetadataTool{} - if _, ok := messageMetadata.Tool[toolCallID]; ok { - metadata = messageMetadata.Tool[toolCallID] + if toolCall.State.Status == opencode.ToolPartStateStatusPending || toolCall.State.Status == opencode.ToolPartStateStatusRunning { + title := renderToolTitle(toolCall, width) + return renderContentBlock(app, title, highlight, width) } var result *string - if toolCall.ToolInvocation.Result != "" { - result = &toolCall.ToolInvocation.Result - } - - if toolCall.ToolInvocation.State == "partial-call" { - title := renderToolTitle(toolCall, messageMetadata, width) - return renderContentBlock(app, title, highlight, width) + if toolCall.State.Output != "" { + result = &toolCall.State.Output } - toolArgsMap := make(map[string]any) - if toolCall.ToolInvocation.Args != nil { - value := toolCall.ToolInvocation.Args + toolInputMap := make(map[string]any) + if toolCall.State.Input != nil { + value := toolCall.State.Input if m, ok := value.(map[string]any); ok { - toolArgsMap = m - keys := make([]string, 0, len(toolArgsMap)) - for key := range toolArgsMap { + toolInputMap = m + keys := make([]string, 0, len(toolInputMap)) + for key := range toolInputMap { keys = append(keys, key) } slices.Sort(keys) @@ -340,7 +331,6 @@ func renderToolDetails( } body := "" - finished := result != nil && *result != "" t := theme.CurrentTheme() backgroundColor := t.BackgroundPanel() borderColor := t.BackgroundPanel() @@ -349,137 +339,128 @@ func renderToolDetails( borderColor = t.BorderActive() } - switch toolCall.ToolInvocation.ToolName { - case "read": - preview := metadata.ExtraFields["preview"] - if preview != nil && toolArgsMap["filePath"] != nil { - filename := toolArgsMap["filePath"].(string) - body = preview.(string) - body = util.RenderFile(filename, body, width, util.WithTruncate(6)) - } - case "edit": - if filename, ok := toolArgsMap["filePath"].(string); ok { - diffField := metadata.ExtraFields["diff"] - if diffField != nil { - patch := diffField.(string) - var formattedDiff string - formattedDiff, _ = diff.FormatUnifiedDiff( - filename, - patch, - diff.WithWidth(width-2), - ) - body = strings.TrimSpace(formattedDiff) - style := styles.NewStyle(). - Background(backgroundColor). - Foreground(t.TextMuted()). - Padding(1, 2). - Width(width - 4) - if highlight { - style = style.Foreground(t.Text()).Bold(true) - } + if toolCall.State.Status == opencode.ToolPartStateStatusCompleted { + metadata := toolCall.State.Metadata.(map[string]any) + switch toolCall.Tool { + case "read": + preview := metadata["preview"] + if preview != nil && toolInputMap["filePath"] != nil { + filename := toolInputMap["filePath"].(string) + body = preview.(string) + body = util.RenderFile(filename, body, width, util.WithTruncate(6)) + } + case "edit": + if filename, ok := toolInputMap["filePath"].(string); ok { + diffField := metadata["diff"] + if diffField != nil { + patch := diffField.(string) + var formattedDiff string + formattedDiff, _ = diff.FormatUnifiedDiff( + filename, + patch, + diff.WithWidth(width-2), + ) + body = strings.TrimSpace(formattedDiff) + style := styles.NewStyle(). + Background(backgroundColor). + Foreground(t.TextMuted()). + Padding(1, 2). + Width(width - 4) + if highlight { + style = style.Foreground(t.Text()).Bold(true) + } - if diagnostics := renderDiagnostics(metadata, filename); diagnostics != "" { - diagnostics = style.Render(diagnostics) - body += "\n" + diagnostics - } + if diagnostics := renderDiagnostics(metadata, filename); diagnostics != "" { + diagnostics = style.Render(diagnostics) + body += "\n" + diagnostics + } - title := renderToolTitle(toolCall, messageMetadata, width) - title = style.Render(title) - content := title + "\n" + body - content = renderContentBlock( - app, - content, - highlight, - width, - WithPadding(0), - WithBorderColor(borderColor), - ) - return content + title := renderToolTitle(toolCall, width) + title = style.Render(title) + content := title + "\n" + body + content = renderContentBlock( + app, + content, + highlight, + width, + WithPadding(0), + WithBorderColor(borderColor), + ) + return content + } } - } - case "write": - if filename, ok := toolArgsMap["filePath"].(string); ok { - if content, ok := toolArgsMap["content"].(string); ok { - body = util.RenderFile(filename, content, width) - if diagnostics := renderDiagnostics(metadata, filename); diagnostics != "" { - body += "\n\n" + diagnostics + case "write": + if filename, ok := toolInputMap["filePath"].(string); ok { + if content, ok := toolInputMap["content"].(string); ok { + body = util.RenderFile(filename, content, width) + if diagnostics := renderDiagnostics(metadata, filename); diagnostics != "" { + body += "\n\n" + diagnostics + } } } - } - case "bash": - stdout := metadata.ExtraFields["stdout"] - if stdout != nil { - command := toolArgsMap["command"].(string) - body = fmt.Sprintf("```console\n> %s\n%s```", command, stdout) - body = util.ToMarkdown(body, width, backgroundColor) - } - case "webfetch": - if format, ok := toolArgsMap["format"].(string); ok && result != nil { - body = *result - body = util.TruncateHeight(body, 10) - if format == "html" || format == "markdown" { + case "bash": + stdout := metadata["stdout"] + if stdout != nil { + command := toolInputMap["command"].(string) + body = fmt.Sprintf("```console\n> %s\n%s```", command, stdout) body = util.ToMarkdown(body, width, backgroundColor) } - } - case "todowrite": - todos := metadata.JSON.ExtraFields["todos"] - if !todos.IsNull() && finished { - strTodos := todos.Raw() - todos := gjson.Parse(strTodos) - for _, todo := range todos.Array() { - content := todo.Get("content").String() - switch todo.Get("status").String() { - case "completed": - body += fmt.Sprintf("- [x] %s\n", content) - // case "in-progress": - // body += fmt.Sprintf("- [ ] %s\n", content) - default: - body += fmt.Sprintf("- [ ] %s\n", content) + case "webfetch": + if format, ok := toolInputMap["format"].(string); ok && result != nil { + body = *result + body = util.TruncateHeight(body, 10) + if format == "html" || format == "markdown" { + body = util.ToMarkdown(body, width, backgroundColor) } } - body = util.ToMarkdown(body, width, backgroundColor) - } - case "task": - summary := metadata.JSON.ExtraFields["summary"] - if !summary.IsNull() { - strValue := summary.Raw() - toolcalls := gjson.Parse(strValue).Array() - - steps := []string{} - for _, toolcall := range toolcalls { - call := toolcall.Value().(map[string]any) - if toolInvocation, ok := call["toolInvocation"].(map[string]any); ok { - data, _ := json.Marshal(toolInvocation) - var toolCall opencode.ToolInvocationPart - _ = json.Unmarshal(data, &toolCall) - - if metadata, ok := call["metadata"].(map[string]any); ok { - data, _ = json.Marshal(metadata) - var toolMetadata opencode.MessageMetadataTool - _ = json.Unmarshal(data, &toolMetadata) - - step := renderToolTitle(toolCall, messageMetadata, width) + case "todowrite": + todos := metadata["todos"] + if todos != nil { + for _, item := range todos.([]any) { + todo := item.(map[string]any) + content := todo["content"].(string) + switch todo["status"] { + case "completed": + body += fmt.Sprintf("- [x] %s\n", content) + // case "in-progress": + // body += fmt.Sprintf("- [ ] %s\n", content) + default: + body += fmt.Sprintf("- [ ] %s\n", content) + } + } + body = util.ToMarkdown(body, width, backgroundColor) + } + case "task": + summary := metadata["summary"] + if summary != nil { + toolcalls := summary.([]any) + steps := []string{} + for _, toolcall := range toolcalls { + call := toolcall.(map[string]any) + if toolInvocation, ok := call["toolInvocation"].(map[string]any); ok { + data, _ := json.Marshal(toolInvocation) + var toolCall opencode.ToolPart + _ = json.Unmarshal(data, &toolCall) + step := renderToolTitle(toolCall, width) step = "∟ " + step steps = append(steps, step) } } + body = strings.Join(steps, "\n") } - body = strings.Join(steps, "\n") - } - default: - if result == nil { - empty := "" - result = &empty + default: + if result == nil { + empty := "" + result = &empty + } + body = *result + body = util.TruncateHeight(body, 10) } - body = *result - body = util.TruncateHeight(body, 10) } error := "" - if err, ok := metadata.ExtraFields["error"].(bool); ok && err { - if message, ok := metadata.ExtraFields["message"].(string); ok { - error = message - } + if toolCall.State.Status == opencode.ToolPartStateStatusError { + error = toolCall.State.Error } if error != "" { @@ -494,7 +475,7 @@ func renderToolDetails( body = util.TruncateHeight(body, 10) } - title := renderToolTitle(toolCall, messageMetadata, width) + title := renderToolTitle(toolCall, width) content := title + "\n\n" + body return renderContentBlock(app, content, highlight, width, WithBorderColor(borderColor)) } @@ -515,20 +496,19 @@ func renderToolName(name string) string { } func renderToolTitle( - toolCall opencode.ToolInvocationPart, - messageMetadata opencode.MessageMetadata, + toolCall opencode.ToolPart, width int, ) string { // TODO: handle truncate to width - if toolCall.ToolInvocation.State == "partial-call" { - return renderToolAction(toolCall.ToolInvocation.ToolName) + if toolCall.State.Status == opencode.ToolPartStateStatusPending { + return renderToolAction(toolCall.Tool) } toolArgs := "" toolArgsMap := make(map[string]any) - if toolCall.ToolInvocation.Args != nil { - value := toolCall.ToolInvocation.Args + if toolCall.State.Input != nil { + value := toolCall.State.Input if m, ok := value.(map[string]any); ok { toolArgsMap = m @@ -546,8 +526,8 @@ func renderToolTitle( } } - title := renderToolName(toolCall.ToolInvocation.ToolName) - switch toolCall.ToolInvocation.ToolName { + title := renderToolName(toolCall.Tool) + switch toolCall.Tool { case "read": toolArgs = renderArgs(&toolArgsMap, "filePath") title = fmt.Sprintf("%s %s", title, toolArgs) @@ -565,7 +545,7 @@ func renderToolTitle( case "todowrite", "todoread": // title is just the tool name default: - toolName := renderToolName(toolCall.ToolInvocation.ToolName) + toolName := renderToolName(toolCall.Tool) title = fmt.Sprintf("%s %s", toolName, toolArgs) } return title @@ -645,8 +625,8 @@ type Diagnostic struct { } // renderDiagnostics formats LSP diagnostics for display in the TUI -func renderDiagnostics(metadata opencode.MessageMetadataTool, filePath string) string { - if diagnosticsData, ok := metadata.ExtraFields["diagnostics"].(map[string]any); ok { +func renderDiagnostics(metadata map[string]any, filePath string) string { + if diagnosticsData, ok := metadata["diagnostics"].(map[string]any); ok { if fileDiagnostics, ok := diagnosticsData[filePath].([]any); ok { var errorDiagnostics []string for _, diagInterface := range fileDiagnostics { diff --git a/packages/tui/internal/components/chat/messages.go b/packages/tui/internal/components/chat/messages.go index a59b5d79e..26bee8714 100644 --- a/packages/tui/internal/components/chat/messages.go +++ b/packages/tui/internal/components/chat/messages.go @@ -99,7 +99,7 @@ func (m *messagesComponent) Update(msg tea.Msg) (tea.Model, tea.Cmd) { } } case opencode.EventListResponseEventMessageUpdated: - if msg.Properties.Info.Metadata.SessionID == m.app.Session.ID { + if msg.Properties.Info.SessionID == m.app.Session.ID { m.renderView(m.width) if m.tail { m.viewport.GotoBottom() @@ -124,19 +124,19 @@ func (m *messagesComponent) renderView(width int) { m.partCount = 0 m.lineCount = 0 - orphanedToolCalls := make([]opencode.ToolInvocationPart, 0) + orphanedToolCalls := make([]opencode.ToolPart, 0) for _, message := range m.app.Messages { var content string var cached bool - switch message.Role { - case opencode.MessageRoleUser: + switch casted := message.(type) { + case opencode.UserMessage: userLoop: - for partIndex, part := range message.Parts { + for partIndex, part := range casted.Parts { switch part := part.AsUnion().(type) { case opencode.TextPart: - remainingParts := message.Parts[partIndex+1:] + remainingParts := casted.Parts[partIndex+1:] fileParts := make([]opencode.FilePart, 0) for _, part := range remainingParts { switch part := part.AsUnion().(type) { @@ -150,7 +150,7 @@ func (m *messagesComponent) renderView(width int) { mediaTypeStyle := styles.NewStyle().Background(t.Secondary()).Foreground(t.BackgroundPanel()).Padding(0, 1) for _, filePart := range fileParts { mediaType := "" - switch filePart.MediaType { + switch filePart.Mime { case "text/plain": mediaType = "txt" case "image/png", "image/jpeg", "image/gif", "image/webp": @@ -175,7 +175,7 @@ func (m *messagesComponent) renderView(width int) { flexItems..., ) - key := m.cache.GenerateKey(message.ID, part.Text, width, m.selectedPart == m.partCount, files) + key := m.cache.GenerateKey(casted.ID, part.Text, width, m.selectedPart == m.partCount, files) content, cached = m.cache.Get(key) if !cached { content = renderText( @@ -199,21 +199,21 @@ func (m *messagesComponent) renderView(width int) { } } - case opencode.MessageRoleAssistant: + case opencode.AssistantMessage: hasTextPart := false - for partIndex, p := range message.Parts { + for partIndex, p := range casted.Parts { switch part := p.AsUnion().(type) { case opencode.TextPart: hasTextPart = true - finished := message.Metadata.Time.Completed > 0 - remainingParts := message.Parts[partIndex+1:] - toolCallParts := make([]opencode.ToolInvocationPart, 0) + finished := casted.Time.Completed > 0 + remainingParts := casted.Parts[partIndex+1:] + toolCallParts := make([]opencode.ToolPart, 0) // sometimes tool calls happen without an assistant message // these should be included in this assistant message as well if len(orphanedToolCalls) > 0 { toolCallParts = append(toolCallParts, orphanedToolCalls...) - orphanedToolCalls = make([]opencode.ToolInvocationPart, 0) + orphanedToolCalls = make([]opencode.ToolPart, 0) } remaining := true @@ -226,9 +226,9 @@ func (m *messagesComponent) renderView(width int) { // we only want tool calls associated with the current text part. // if we hit another text part, we're done. remaining = false - case opencode.ToolInvocationPart: + case opencode.ToolPart: toolCallParts = append(toolCallParts, part) - if part.ToolInvocation.State != "result" { + if part.State.Status != opencode.ToolPartStateStatusCompleted || part.State.Status != opencode.ToolPartStateStatusError { // i don't think there's a case where a tool call isn't in result state // and the message time is 0, but just in case finished = false @@ -237,14 +237,14 @@ func (m *messagesComponent) renderView(width int) { } if finished { - key := m.cache.GenerateKey(message.ID, p.Text, width, m.showToolDetails, m.selectedPart == m.partCount) + key := m.cache.GenerateKey(casted.ID, p.Text, width, m.showToolDetails, m.selectedPart == m.partCount) content, cached = m.cache.Get(key) if !cached { content = renderText( m.app, message, p.Text, - message.Metadata.Assistant.ModelID, + casted.ModelID, m.showToolDetails, m.partCount == m.selectedPart, width, @@ -258,7 +258,7 @@ func (m *messagesComponent) renderView(width int) { m.app, message, p.Text, - message.Metadata.Assistant.ModelID, + casted.ModelID, m.showToolDetails, m.partCount == m.selectedPart, width, @@ -270,7 +270,7 @@ func (m *messagesComponent) renderView(width int) { m = m.updateSelected(content, p.Text) blocks = append(blocks, content) } - case opencode.ToolInvocationPart: + case opencode.ToolPart: if !m.showToolDetails { if !hasTextPart { orphanedToolCalls = append(orphanedToolCalls, part) @@ -278,9 +278,9 @@ func (m *messagesComponent) renderView(width int) { continue } - if part.ToolInvocation.State == "result" { - key := m.cache.GenerateKey(message.ID, - part.ToolInvocation.ToolCallID, + if part.State.Status == opencode.ToolPartStateStatusCompleted || part.State.Status == opencode.ToolPartStateStatusError { + key := m.cache.GenerateKey(casted.ID, + part.ID, m.showToolDetails, width, m.partCount == m.selectedPart, @@ -290,7 +290,6 @@ func (m *messagesComponent) renderView(width int) { content = renderToolDetails( m.app, part, - message.Metadata, m.partCount == m.selectedPart, width, ) @@ -301,7 +300,6 @@ func (m *messagesComponent) renderView(width int) { content = renderToolDetails( m.app, part, - message.Metadata, m.partCount == m.selectedPart, width, ) @@ -315,14 +313,16 @@ func (m *messagesComponent) renderView(width int) { } error := "" - switch err := message.Metadata.Error.AsUnion().(type) { - case nil: - case opencode.MessageMetadataErrorMessageOutputLengthError: - error = "Message output length exceeded" - case opencode.ProviderAuthError: - error = err.Data.Message - case opencode.UnknownError: - error = err.Data.Message + if assistant, ok := message.(opencode.AssistantMessage); ok { + switch err := assistant.Error.AsUnion().(type) { + case nil: + case opencode.AssistantMessageErrorMessageOutputLengthError: + error = "Message output length exceeded" + case opencode.ProviderAuthError: + error = err.Data.Message + case opencode.UnknownError: + error = err.Data.Message + } } if error != "" { diff --git a/packages/tui/internal/components/status/status.go b/packages/tui/internal/components/status/status.go index 791267e0a..7d5820de3 100644 --- a/packages/tui/internal/components/status/status.go +++ b/packages/tui/internal/components/status/status.go @@ -6,6 +6,7 @@ import ( tea "github.com/charmbracelet/bubbletea/v2" "github.com/charmbracelet/lipgloss/v2" + "github.com/sst/opencode-sdk-go" "github.com/sst/opencode/internal/app" "github.com/sst/opencode/internal/styles" "github.com/sst/opencode/internal/theme" @@ -101,18 +102,20 @@ func (m statusComponent) View() string { contextWindow := m.app.Model.Limit.Context for _, message := range m.app.Messages { - cost += message.Metadata.Assistant.Cost - usage := message.Metadata.Assistant.Tokens - if usage.Output > 0 { - if message.Metadata.Assistant.Summary { - tokens = usage.Output - continue + if assistant, ok := message.(opencode.AssistantMessage); ok { + cost += assistant.Cost + usage := assistant.Tokens + if usage.Output > 0 { + if assistant.Summary { + tokens = usage.Output + continue + } + tokens = (usage.Input + + usage.Cache.Write + + usage.Cache.Read + + usage.Output + + usage.Reasoning) } - tokens = (usage.Input + - usage.Cache.Write + - usage.Cache.Read + - usage.Output + - usage.Reasoning) } } diff --git a/packages/tui/internal/tui/tui.go b/packages/tui/internal/tui/tui.go index 150a1b26b..e32575bd4 100644 --- a/packages/tui/internal/tui/tui.go +++ b/packages/tui/internal/tui/tui.go @@ -363,7 +363,7 @@ func (a appModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { case opencode.EventListResponseEventSessionDeleted: if a.app.Session != nil && msg.Properties.Info.ID == a.app.Session.ID { a.app.Session = &opencode.Session{} - a.app.Messages = []opencode.Message{} + a.app.Messages = []opencode.MessageUnion{} } return a, toast.NewSuccessToast("Session deleted successfully") case opencode.EventListResponseEventSessionUpdated: @@ -371,7 +371,7 @@ func (a appModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { a.app.Session = &msg.Properties.Info } case opencode.EventListResponseEventMessageUpdated: - if msg.Properties.Info.Metadata.SessionID == a.app.Session.ID { + if msg.Properties.Info.SessionID == a.app.Session.ID { exists := false optimisticReplaced := false @@ -379,12 +379,15 @@ func (a appModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { if msg.Properties.Info.Role == opencode.MessageRoleUser { // Look for optimistic messages to replace for i, m := range a.app.Messages { - if strings.HasPrefix(m.ID, "optimistic-") && m.Role == opencode.MessageRoleUser { - // Replace the optimistic message with the real one - a.app.Messages[i] = msg.Properties.Info - exists = true - optimisticReplaced = true - break + switch m := m.(type) { + case opencode.UserMessage: + if strings.HasPrefix(m.ID, "optimistic-") && m.Role == opencode.UserMessageRoleUser { + // Replace the optimistic message with the real one + a.app.Messages[i] = msg.Properties.Info.AsUnion() + exists = true + optimisticReplaced = true + break + } } } } @@ -392,8 +395,15 @@ func (a appModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { // If not replacing optimistic, check for existing message with same ID if !optimisticReplaced { for i, m := range a.app.Messages { - if m.ID == msg.Properties.Info.ID { - a.app.Messages[i] = msg.Properties.Info + var id string + switch m := m.(type) { + case opencode.UserMessage: + id = m.ID + case opencode.AssistantMessage: + id = m.ID + } + if id == msg.Properties.Info.ID { + a.app.Messages[i] = msg.Properties.Info.AsUnion() exists = true break } @@ -401,7 +411,7 @@ func (a appModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { } if !exists { - a.app.Messages = append(a.app.Messages, msg.Properties.Info) + a.app.Messages = append(a.app.Messages, msg.Properties.Info.AsUnion()) } } case opencode.EventListResponseEventSessionError: @@ -462,7 +472,10 @@ func (a appModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { return a, toast.NewErrorToast("Failed to open session") } a.app.Session = msg - a.app.Messages = messages + a.app.Messages = make([]opencode.MessageUnion, 0) + for _, message := range messages { + a.app.Messages = append(a.app.Messages, message.AsUnion()) + } return a, util.CmdHandler(app.SessionLoadedMsg{}) case app.ModelSelectedMsg: a.app.Provider = &msg.Provider @@ -813,7 +826,7 @@ func (a appModel) executeCommand(command commands.Command) (tea.Model, tea.Cmd) return a, nil } a.app.Session = &opencode.Session{} - a.app.Messages = []opencode.Message{} + a.app.Messages = []opencode.MessageUnion{} cmds = append(cmds, util.CmdHandler(app.SessionClearedMsg{})) case commands.SessionListCommand: sessionDialog := dialog.NewSessionDialog(a.app) diff --git a/packages/tui/sdk/.github/workflows/ci.yml b/packages/tui/sdk/.github/workflows/ci.yml index 4bf1e907c..0f5d45dc2 100644 --- a/packages/tui/sdk/.github/workflows/ci.yml +++ b/packages/tui/sdk/.github/workflows/ci.yml @@ -2,15 +2,15 @@ name: CI on: push: branches-ignore: - - 'generated' - - 'codegen/**' - - 'integrated/**' - - 'stl-preview-head/**' - - 'stl-preview-base/**' + - "generated" + - "codegen/**" + - "integrated/**" + - "stl-preview-head/**" + - "stl-preview-base/**" pull_request: branches-ignore: - - 'stl-preview-head/**' - - 'stl-preview-base/**' + - "stl-preview-head/**" + - "stl-preview-base/**" jobs: lint: diff --git a/packages/tui/sdk/.release-please-manifest.json b/packages/tui/sdk/.release-please-manifest.json index c373724dc..332798e1b 100644 --- a/packages/tui/sdk/.release-please-manifest.json +++ b/packages/tui/sdk/.release-please-manifest.json @@ -1,3 +1,3 @@ { ".": "0.1.0-alpha.8" -}
\ No newline at end of file +} diff --git a/packages/tui/sdk/.stats.yml b/packages/tui/sdk/.stats.yml index ab6c4a206..068170cae 100644 --- a/packages/tui/sdk/.stats.yml +++ b/packages/tui/sdk/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 20 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/opencode%2Fopencode-945f9da9e9a4c4008834deef63e4346c0076e020eed3d3c98c249095033c1ac5.yml -openapi_spec_hash: 522a44f6cb0677435fe2ac7693848ad7 -config_hash: 6c8822d278ba83456e5eed6d774ca230 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/opencode%2Fopencode-15eeb028f79b9a065b4e54a6ea6a58631e9bd5004f97820f0c79d18e3f8bac84.yml +openapi_spec_hash: 38c8bacb6c8e4c46852a3e81e3fb9fda +config_hash: e03e9d1aad76081fa1163086e89f201b diff --git a/packages/tui/sdk/CHANGELOG.md b/packages/tui/sdk/CHANGELOG.md index bc407fad9..fe25e6e8b 100644 --- a/packages/tui/sdk/CHANGELOG.md +++ b/packages/tui/sdk/CHANGELOG.md @@ -6,7 +6,7 @@ Full Changelog: [v0.1.0-alpha.7...v0.1.0-alpha.8](https://github.com/sst/opencod ### Features -* **api:** update via SDK Studio ([651e937](https://github.com/sst/opencode-sdk-go/commit/651e937c334e1caba3b968e6cac865c219879519)) +- **api:** update via SDK Studio ([651e937](https://github.com/sst/opencode-sdk-go/commit/651e937c334e1caba3b968e6cac865c219879519)) ## 0.1.0-alpha.7 (2025-06-30) @@ -14,13 +14,12 @@ Full Changelog: [v0.1.0-alpha.6...v0.1.0-alpha.7](https://github.com/sst/opencod ### Features -* **api:** update via SDK Studio ([13550a5](https://github.com/sst/opencode-sdk-go/commit/13550a5c65d77325e945ed99fe0799cd1107b775)) -* **api:** update via SDK Studio ([7b73730](https://github.com/sst/opencode-sdk-go/commit/7b73730c7fa62ba966dda3541c3e97b49be8d2bf)) - +- **api:** update via SDK Studio ([13550a5](https://github.com/sst/opencode-sdk-go/commit/13550a5c65d77325e945ed99fe0799cd1107b775)) +- **api:** update via SDK Studio ([7b73730](https://github.com/sst/opencode-sdk-go/commit/7b73730c7fa62ba966dda3541c3e97b49be8d2bf)) ### Chores -* **ci:** only run for pushes and fork pull requests ([bea59b8](https://github.com/sst/opencode-sdk-go/commit/bea59b886800ef555f89c47a9256d6392ed2e53d)) +- **ci:** only run for pushes and fork pull requests ([bea59b8](https://github.com/sst/opencode-sdk-go/commit/bea59b886800ef555f89c47a9256d6392ed2e53d)) ## 0.1.0-alpha.6 (2025-06-28) @@ -28,7 +27,7 @@ Full Changelog: [v0.1.0-alpha.5...v0.1.0-alpha.6](https://github.com/sst/opencod ### Bug Fixes -* don't try to deserialize as json when ResponseBodyInto is []byte ([5988d04](https://github.com/sst/opencode-sdk-go/commit/5988d04839cb78b6613057280b91b72a60fef33d)) +- don't try to deserialize as json when ResponseBodyInto is []byte ([5988d04](https://github.com/sst/opencode-sdk-go/commit/5988d04839cb78b6613057280b91b72a60fef33d)) ## 0.1.0-alpha.5 (2025-06-27) @@ -36,7 +35,7 @@ Full Changelog: [v0.1.0-alpha.4...v0.1.0-alpha.5](https://github.com/sst/opencod ### Features -* **api:** update via SDK Studio ([9e39a59](https://github.com/sst/opencode-sdk-go/commit/9e39a59b3d5d1bd5e64633732521fb28362cc70e)) +- **api:** update via SDK Studio ([9e39a59](https://github.com/sst/opencode-sdk-go/commit/9e39a59b3d5d1bd5e64633732521fb28362cc70e)) ## 0.1.0-alpha.4 (2025-06-27) @@ -44,7 +43,7 @@ Full Changelog: [v0.1.0-alpha.3...v0.1.0-alpha.4](https://github.com/sst/opencod ### Features -* **api:** update via SDK Studio ([9609d1b](https://github.com/sst/opencode-sdk-go/commit/9609d1b1db7806d00cb846c9914cb4935cdedf52)) +- **api:** update via SDK Studio ([9609d1b](https://github.com/sst/opencode-sdk-go/commit/9609d1b1db7806d00cb846c9914cb4935cdedf52)) ## 0.1.0-alpha.3 (2025-06-27) @@ -52,7 +51,7 @@ Full Changelog: [v0.1.0-alpha.2...v0.1.0-alpha.3](https://github.com/sst/opencod ### Features -* **api:** update via SDK Studio ([57f3230](https://github.com/sst/opencode-sdk-go/commit/57f32309023cc1f0f20c20d02a3907e390a71f61)) +- **api:** update via SDK Studio ([57f3230](https://github.com/sst/opencode-sdk-go/commit/57f32309023cc1f0f20c20d02a3907e390a71f61)) ## 0.1.0-alpha.2 (2025-06-27) @@ -60,7 +59,7 @@ Full Changelog: [v0.1.0-alpha.1...v0.1.0-alpha.2](https://github.com/sst/opencod ### Features -* **api:** update via SDK Studio ([a766f1c](https://github.com/sst/opencode-sdk-go/commit/a766f1c54f02bbc1380151b0e22d97cc2c5892e6)) +- **api:** update via SDK Studio ([a766f1c](https://github.com/sst/opencode-sdk-go/commit/a766f1c54f02bbc1380151b0e22d97cc2c5892e6)) ## 0.1.0-alpha.1 (2025-06-27) @@ -68,6 +67,6 @@ Full Changelog: [v0.0.1-alpha.0...v0.1.0-alpha.1](https://github.com/sst/opencod ### Features -* **api:** update via SDK Studio ([27b7376](https://github.com/sst/opencode-sdk-go/commit/27b7376310466ee17a63f2104f546b53a2b8361a)) -* **api:** update via SDK Studio ([0a73e04](https://github.com/sst/opencode-sdk-go/commit/0a73e04c23c90b2061611edaa8fd6282dc0ce397)) -* **api:** update via SDK Studio ([9b7883a](https://github.com/sst/opencode-sdk-go/commit/9b7883a144eeac526d9d04538e0876a9d18bb844)) +- **api:** update via SDK Studio ([27b7376](https://github.com/sst/opencode-sdk-go/commit/27b7376310466ee17a63f2104f546b53a2b8361a)) +- **api:** update via SDK Studio ([0a73e04](https://github.com/sst/opencode-sdk-go/commit/0a73e04c23c90b2061611edaa8fd6282dc0ce397)) +- **api:** update via SDK Studio ([9b7883a](https://github.com/sst/opencode-sdk-go/commit/9b7883a144eeac526d9d04538e0876a9d18bb844)) diff --git a/packages/tui/sdk/api.md b/packages/tui/sdk/api.md index 4ac9edcf6..b8f3769df 100644 --- a/packages/tui/sdk/api.md +++ b/packages/tui/sdk/api.md @@ -71,30 +71,25 @@ Methods: Params Types: - <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#FilePartParam">FilePartParam</a> -- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#MessagePartUnionParam">MessagePartUnionParam</a> -- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#ReasoningPartParam">ReasoningPartParam</a> -- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SourceURLPartParam">SourceURLPartParam</a> -- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#StepStartPartParam">StepStartPartParam</a> - <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#TextPartParam">TextPartParam</a> -- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#ToolCallParam">ToolCallParam</a> -- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#ToolInvocationPartParam">ToolInvocationPartParam</a> -- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#ToolPartialCallParam">ToolPartialCallParam</a> -- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#ToolResultParam">ToolResultParam</a> +- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#UserMessagePartUnionParam">UserMessagePartUnionParam</a> Response Types: +- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#AssistantMessage">AssistantMessage</a> +- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#AssistantMessagePart">AssistantMessagePart</a> - <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#FilePart">FilePart</a> - <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#Message">Message</a> -- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#MessagePart">MessagePart</a> -- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#ReasoningPart">ReasoningPart</a> - <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#Session">Session</a> -- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SourceURLPart">SourceURLPart</a> - <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#StepStartPart">StepStartPart</a> - <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#TextPart">TextPart</a> -- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#ToolCall">ToolCall</a> -- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#ToolInvocationPart">ToolInvocationPart</a> -- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#ToolPartialCall">ToolPartialCall</a> -- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#ToolResult">ToolResult</a> +- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#ToolPart">ToolPart</a> +- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#ToolStateCompleted">ToolStateCompleted</a> +- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#ToolStateError">ToolStateError</a> +- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#ToolStatePending">ToolStatePending</a> +- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#ToolStateRunning">ToolStateRunning</a> +- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#UserMessage">UserMessage</a> +- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#UserMessagePart">UserMessagePart</a> Methods: @@ -102,7 +97,7 @@ Methods: - <code title="get /session">client.Session.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionService.List">List</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>) ([]<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#Session">Session</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code> - <code title="delete /session/{id}">client.Session.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionService.Delete">Delete</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, id <a href="https://pkg.go.dev/builtin#string">string</a>) (<a href="https://pkg.go.dev/builtin#bool">bool</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code> - <code title="post /session/{id}/abort">client.Session.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionService.Abort">Abort</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, id <a href="https://pkg.go.dev/builtin#string">string</a>) (<a href="https://pkg.go.dev/builtin#bool">bool</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code> -- <code title="post /session/{id}/message">client.Session.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionService.Chat">Chat</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, id <a href="https://pkg.go.dev/builtin#string">string</a>, body <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionChatParams">SessionChatParams</a>) (<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#Message">Message</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code> +- <code title="post /session/{id}/message">client.Session.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionService.Chat">Chat</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, id <a href="https://pkg.go.dev/builtin#string">string</a>, body <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionChatParams">SessionChatParams</a>) (<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#AssistantMessage">AssistantMessage</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code> - <code title="post /session/{id}/init">client.Session.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionService.Init">Init</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, id <a href="https://pkg.go.dev/builtin#string">string</a>, body <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionInitParams">SessionInitParams</a>) (<a href="https://pkg.go.dev/builtin#bool">bool</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code> - <code title="get /session/{id}/message">client.Session.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionService.Messages">Messages</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, id <a href="https://pkg.go.dev/builtin#string">string</a>) ([]<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#Message">Message</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code> - <code title="post /session/{id}/share">client.Session.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#SessionService.Share">Share</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, id <a href="https://pkg.go.dev/builtin#string">string</a>) (<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#Session">Session</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code> diff --git a/packages/tui/sdk/event.go b/packages/tui/sdk/event.go index ed92b2ae3..48eb129f5 100644 --- a/packages/tui/sdk/event.go +++ b/packages/tui/sdk/event.go @@ -51,8 +51,8 @@ type EventListResponse struct { // [EventListResponseEventLspClientDiagnosticsProperties], // [EventListResponseEventPermissionUpdatedProperties], // [EventListResponseEventFileEditedProperties], - // [EventListResponseEventStorageWriteProperties], // [EventListResponseEventInstallationUpdatedProperties], + // [EventListResponseEventStorageWriteProperties], // [EventListResponseEventMessageUpdatedProperties], // [EventListResponseEventMessageRemovedProperties], // [EventListResponseEventMessagePartUpdatedProperties], @@ -95,9 +95,9 @@ func (r *EventListResponse) UnmarshalJSON(data []byte) (err error) { // Possible runtime types of the union are // [EventListResponseEventLspClientDiagnostics], // [EventListResponseEventPermissionUpdated], [EventListResponseEventFileEdited], -// [EventListResponseEventStorageWrite], // [EventListResponseEventInstallationUpdated], -// [EventListResponseEventMessageUpdated], [EventListResponseEventMessageRemoved], +// [EventListResponseEventStorageWrite], [EventListResponseEventMessageUpdated], +// [EventListResponseEventMessageRemoved], // [EventListResponseEventMessagePartUpdated], // [EventListResponseEventSessionUpdated], [EventListResponseEventSessionDeleted], // [EventListResponseEventSessionIdle], [EventListResponseEventSessionError], @@ -108,9 +108,9 @@ func (r EventListResponse) AsUnion() EventListResponseUnion { // Union satisfied by [EventListResponseEventLspClientDiagnostics], // [EventListResponseEventPermissionUpdated], [EventListResponseEventFileEdited], -// [EventListResponseEventStorageWrite], // [EventListResponseEventInstallationUpdated], -// [EventListResponseEventMessageUpdated], [EventListResponseEventMessageRemoved], +// [EventListResponseEventStorageWrite], [EventListResponseEventMessageUpdated], +// [EventListResponseEventMessageRemoved], // [EventListResponseEventMessagePartUpdated], // [EventListResponseEventSessionUpdated], [EventListResponseEventSessionDeleted], // [EventListResponseEventSessionIdle], [EventListResponseEventSessionError] or @@ -140,13 +140,13 @@ func init() { }, apijson.UnionVariant{ TypeFilter: gjson.JSON, - Type: reflect.TypeOf(EventListResponseEventStorageWrite{}), - DiscriminatorValue: "storage.write", + Type: reflect.TypeOf(EventListResponseEventInstallationUpdated{}), + DiscriminatorValue: "installation.updated", }, apijson.UnionVariant{ TypeFilter: gjson.JSON, - Type: reflect.TypeOf(EventListResponseEventInstallationUpdated{}), - DiscriminatorValue: "installation.updated", + Type: reflect.TypeOf(EventListResponseEventStorageWrite{}), + DiscriminatorValue: "storage.write", }, apijson.UnionVariant{ TypeFilter: gjson.JSON, @@ -402,123 +402,123 @@ func (r EventListResponseEventFileEditedType) IsKnown() bool { return false } -type EventListResponseEventStorageWrite struct { - Properties EventListResponseEventStorageWriteProperties `json:"properties,required"` - Type EventListResponseEventStorageWriteType `json:"type,required"` - JSON eventListResponseEventStorageWriteJSON `json:"-"` +type EventListResponseEventInstallationUpdated struct { + Properties EventListResponseEventInstallationUpdatedProperties `json:"properties,required"` + Type EventListResponseEventInstallationUpdatedType `json:"type,required"` + JSON eventListResponseEventInstallationUpdatedJSON `json:"-"` } -// eventListResponseEventStorageWriteJSON contains the JSON metadata for the struct -// [EventListResponseEventStorageWrite] -type eventListResponseEventStorageWriteJSON struct { +// eventListResponseEventInstallationUpdatedJSON contains the JSON metadata for the +// struct [EventListResponseEventInstallationUpdated] +type eventListResponseEventInstallationUpdatedJSON struct { Properties apijson.Field Type apijson.Field raw string ExtraFields map[string]apijson.Field } -func (r *EventListResponseEventStorageWrite) UnmarshalJSON(data []byte) (err error) { +func (r *EventListResponseEventInstallationUpdated) UnmarshalJSON(data []byte) (err error) { return apijson.UnmarshalRoot(data, r) } -func (r eventListResponseEventStorageWriteJSON) RawJSON() string { +func (r eventListResponseEventInstallationUpdatedJSON) RawJSON() string { return r.raw } -func (r EventListResponseEventStorageWrite) implementsEventListResponse() {} +func (r EventListResponseEventInstallationUpdated) implementsEventListResponse() {} -type EventListResponseEventStorageWriteProperties struct { - Key string `json:"key,required"` - Content interface{} `json:"content"` - JSON eventListResponseEventStorageWritePropertiesJSON `json:"-"` +type EventListResponseEventInstallationUpdatedProperties struct { + Version string `json:"version,required"` + JSON eventListResponseEventInstallationUpdatedPropertiesJSON `json:"-"` } -// eventListResponseEventStorageWritePropertiesJSON contains the JSON metadata for -// the struct [EventListResponseEventStorageWriteProperties] -type eventListResponseEventStorageWritePropertiesJSON struct { - Key apijson.Field - Content apijson.Field +// eventListResponseEventInstallationUpdatedPropertiesJSON contains the JSON +// metadata for the struct [EventListResponseEventInstallationUpdatedProperties] +type eventListResponseEventInstallationUpdatedPropertiesJSON struct { + Version apijson.Field raw string ExtraFields map[string]apijson.Field } -func (r *EventListResponseEventStorageWriteProperties) UnmarshalJSON(data []byte) (err error) { +func (r *EventListResponseEventInstallationUpdatedProperties) UnmarshalJSON(data []byte) (err error) { return apijson.UnmarshalRoot(data, r) } -func (r eventListResponseEventStorageWritePropertiesJSON) RawJSON() string { +func (r eventListResponseEventInstallationUpdatedPropertiesJSON) RawJSON() string { return r.raw } -type EventListResponseEventStorageWriteType string +type EventListResponseEventInstallationUpdatedType string const ( - EventListResponseEventStorageWriteTypeStorageWrite EventListResponseEventStorageWriteType = "storage.write" + EventListResponseEventInstallationUpdatedTypeInstallationUpdated EventListResponseEventInstallationUpdatedType = "installation.updated" ) -func (r EventListResponseEventStorageWriteType) IsKnown() bool { +func (r EventListResponseEventInstallationUpdatedType) IsKnown() bool { switch r { - case EventListResponseEventStorageWriteTypeStorageWrite: + case EventListResponseEventInstallationUpdatedTypeInstallationUpdated: return true } return false } -type EventListResponseEventInstallationUpdated struct { - Properties EventListResponseEventInstallationUpdatedProperties `json:"properties,required"` - Type EventListResponseEventInstallationUpdatedType `json:"type,required"` - JSON eventListResponseEventInstallationUpdatedJSON `json:"-"` +type EventListResponseEventStorageWrite struct { + Properties EventListResponseEventStorageWriteProperties `json:"properties,required"` + Type EventListResponseEventStorageWriteType `json:"type,required"` + JSON eventListResponseEventStorageWriteJSON `json:"-"` } -// eventListResponseEventInstallationUpdatedJSON contains the JSON metadata for the -// struct [EventListResponseEventInstallationUpdated] -type eventListResponseEventInstallationUpdatedJSON struct { +// eventListResponseEventStorageWriteJSON contains the JSON metadata for the struct +// [EventListResponseEventStorageWrite] +type eventListResponseEventStorageWriteJSON struct { Properties apijson.Field Type apijson.Field raw string ExtraFields map[string]apijson.Field } -func (r *EventListResponseEventInstallationUpdated) UnmarshalJSON(data []byte) (err error) { +func (r *EventListResponseEventStorageWrite) UnmarshalJSON(data []byte) (err error) { return apijson.UnmarshalRoot(data, r) } -func (r eventListResponseEventInstallationUpdatedJSON) RawJSON() string { +func (r eventListResponseEventStorageWriteJSON) RawJSON() string { return r.raw } -func (r EventListResponseEventInstallationUpdated) implementsEventListResponse() {} +func (r EventListResponseEventStorageWrite) implementsEventListResponse() {} -type EventListResponseEventInstallationUpdatedProperties struct { - Version string `json:"version,required"` - JSON eventListResponseEventInstallationUpdatedPropertiesJSON `json:"-"` +type EventListResponseEventStorageWriteProperties struct { + Key string `json:"key,required"` + Content interface{} `json:"content"` + JSON eventListResponseEventStorageWritePropertiesJSON `json:"-"` } -// eventListResponseEventInstallationUpdatedPropertiesJSON contains the JSON -// metadata for the struct [EventListResponseEventInstallationUpdatedProperties] -type eventListResponseEventInstallationUpdatedPropertiesJSON struct { - Version apijson.Field +// eventListResponseEventStorageWritePropertiesJSON contains the JSON metadata for +// the struct [EventListResponseEventStorageWriteProperties] +type eventListResponseEventStorageWritePropertiesJSON struct { + Key apijson.Field + Content apijson.Field raw string ExtraFields map[string]apijson.Field } -func (r *EventListResponseEventInstallationUpdatedProperties) UnmarshalJSON(data []byte) (err error) { +func (r *EventListResponseEventStorageWriteProperties) UnmarshalJSON(data []byte) (err error) { return apijson.UnmarshalRoot(data, r) } -func (r eventListResponseEventInstallationUpdatedPropertiesJSON) RawJSON() string { +func (r eventListResponseEventStorageWritePropertiesJSON) RawJSON() string { return r.raw } -type EventListResponseEventInstallationUpdatedType string +type EventListResponseEventStorageWriteType string const ( - EventListResponseEventInstallationUpdatedTypeInstallationUpdated EventListResponseEventInstallationUpdatedType = "installation.updated" + EventListResponseEventStorageWriteTypeStorageWrite EventListResponseEventStorageWriteType = "storage.write" ) -func (r EventListResponseEventInstallationUpdatedType) IsKnown() bool { +func (r EventListResponseEventStorageWriteType) IsKnown() bool { switch r { - case EventListResponseEventInstallationUpdatedTypeInstallationUpdated: + case EventListResponseEventStorageWriteTypeStorageWrite: return true } return false @@ -673,7 +673,7 @@ func (r EventListResponseEventMessagePartUpdated) implementsEventListResponse() type EventListResponseEventMessagePartUpdatedProperties struct { MessageID string `json:"messageID,required"` - Part MessagePart `json:"part,required"` + Part AssistantMessagePart `json:"part,required"` SessionID string `json:"sessionID,required"` JSON eventListResponseEventMessagePartUpdatedPropertiesJSON `json:"-"` } @@ -1159,8 +1159,8 @@ const ( EventListResponseTypeLspClientDiagnostics EventListResponseType = "lsp.client.diagnostics" EventListResponseTypePermissionUpdated EventListResponseType = "permission.updated" EventListResponseTypeFileEdited EventListResponseType = "file.edited" - EventListResponseTypeStorageWrite EventListResponseType = "storage.write" EventListResponseTypeInstallationUpdated EventListResponseType = "installation.updated" + EventListResponseTypeStorageWrite EventListResponseType = "storage.write" EventListResponseTypeMessageUpdated EventListResponseType = "message.updated" EventListResponseTypeMessageRemoved EventListResponseType = "message.removed" EventListResponseTypeMessagePartUpdated EventListResponseType = "message.part.updated" @@ -1173,7 +1173,7 @@ const ( func (r EventListResponseType) IsKnown() bool { switch r { - case EventListResponseTypeLspClientDiagnostics, EventListResponseTypePermissionUpdated, EventListResponseTypeFileEdited, EventListResponseTypeStorageWrite, EventListResponseTypeInstallationUpdated, EventListResponseTypeMessageUpdated, EventListResponseTypeMessageRemoved, EventListResponseTypeMessagePartUpdated, EventListResponseTypeSessionUpdated, EventListResponseTypeSessionDeleted, EventListResponseTypeSessionIdle, EventListResponseTypeSessionError, EventListResponseTypeFileWatcherUpdated: + case EventListResponseTypeLspClientDiagnostics, EventListResponseTypePermissionUpdated, EventListResponseTypeFileEdited, EventListResponseTypeInstallationUpdated, EventListResponseTypeStorageWrite, EventListResponseTypeMessageUpdated, EventListResponseTypeMessageRemoved, EventListResponseTypeMessagePartUpdated, EventListResponseTypeSessionUpdated, EventListResponseTypeSessionDeleted, EventListResponseTypeSessionIdle, EventListResponseTypeSessionError, EventListResponseTypeFileWatcherUpdated: return true } return false diff --git a/packages/tui/sdk/release-please-config.json b/packages/tui/sdk/release-please-config.json index a38198eca..32960ce27 100644 --- a/packages/tui/sdk/release-please-config.json +++ b/packages/tui/sdk/release-please-config.json @@ -60,8 +60,5 @@ } ], "release-type": "go", - "extra-files": [ - "internal/version.go", - "README.md" - ] -}
\ No newline at end of file + "extra-files": ["internal/version.go", "README.md"] +} diff --git a/packages/tui/sdk/session.go b/packages/tui/sdk/session.go index e8216a1fd..816ee7e31 100644 --- a/packages/tui/sdk/session.go +++ b/packages/tui/sdk/session.go @@ -77,7 +77,7 @@ func (r *SessionService) Abort(ctx context.Context, id string, opts ...option.Re } // Create and send a new message to a session -func (r *SessionService) Chat(ctx context.Context, id string, body SessionChatParams, opts ...option.RequestOption) (res *Message, err error) { +func (r *SessionService) Chat(ctx context.Context, id string, body SessionChatParams, opts ...option.RequestOption) (res *AssistantMessage, err error) { opts = append(r.Options[:], opts...) if id == "" { err = errors.New("missing required id parameter") @@ -148,256 +148,124 @@ func (r *SessionService) Unshare(ctx context.Context, id string, opts ...option. return } -type FilePart struct { - MediaType string `json:"mediaType,required"` - Type FilePartType `json:"type,required"` - URL string `json:"url,required"` - Filename string `json:"filename"` - JSON filePartJSON `json:"-"` -} - -// filePartJSON contains the JSON metadata for the struct [FilePart] -type filePartJSON struct { - MediaType apijson.Field - Type apijson.Field - URL apijson.Field - Filename apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *FilePart) UnmarshalJSON(data []byte) (err error) { - return apijson.UnmarshalRoot(data, r) -} - -func (r filePartJSON) RawJSON() string { - return r.raw -} - -func (r FilePart) implementsMessagePart() {} - -type FilePartType string - -const ( - FilePartTypeFile FilePartType = "file" -) - -func (r FilePartType) IsKnown() bool { - switch r { - case FilePartTypeFile: - return true - } - return false -} - -type FilePartParam struct { - MediaType param.Field[string] `json:"mediaType,required"` - Type param.Field[FilePartType] `json:"type,required"` - URL param.Field[string] `json:"url,required"` - Filename param.Field[string] `json:"filename"` -} - -func (r FilePartParam) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) -} - -func (r FilePartParam) implementsMessagePartUnionParam() {} - -type Message struct { - ID string `json:"id,required"` - Metadata MessageMetadata `json:"metadata,required"` - Parts []MessagePart `json:"parts,required"` - Role MessageRole `json:"role,required"` - JSON messageJSON `json:"-"` -} - -// messageJSON contains the JSON metadata for the struct [Message] -type messageJSON struct { +type AssistantMessage struct { + ID string `json:"id,required"` + Cost float64 `json:"cost,required"` + ModelID string `json:"modelID,required"` + Parts []AssistantMessagePart `json:"parts,required"` + Path AssistantMessagePath `json:"path,required"` + ProviderID string `json:"providerID,required"` + Role AssistantMessageRole `json:"role,required"` + SessionID string `json:"sessionID,required"` + System []string `json:"system,required"` + Time AssistantMessageTime `json:"time,required"` + Tokens AssistantMessageTokens `json:"tokens,required"` + Error AssistantMessageError `json:"error"` + Summary bool `json:"summary"` + JSON assistantMessageJSON `json:"-"` +} + +// assistantMessageJSON contains the JSON metadata for the struct +// [AssistantMessage] +type assistantMessageJSON struct { ID apijson.Field - Metadata apijson.Field + Cost apijson.Field + ModelID apijson.Field Parts apijson.Field + Path apijson.Field + ProviderID apijson.Field Role apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *Message) UnmarshalJSON(data []byte) (err error) { - return apijson.UnmarshalRoot(data, r) -} - -func (r messageJSON) RawJSON() string { - return r.raw -} - -type MessageMetadata struct { - SessionID string `json:"sessionID,required"` - Time MessageMetadataTime `json:"time,required"` - Tool map[string]MessageMetadataTool `json:"tool,required"` - Assistant MessageMetadataAssistant `json:"assistant"` - Error MessageMetadataError `json:"error"` - Snapshot string `json:"snapshot"` - JSON messageMetadataJSON `json:"-"` -} - -// messageMetadataJSON contains the JSON metadata for the struct [MessageMetadata] -type messageMetadataJSON struct { SessionID apijson.Field + System apijson.Field Time apijson.Field - Tool apijson.Field - Assistant apijson.Field + Tokens apijson.Field Error apijson.Field - Snapshot apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *MessageMetadata) UnmarshalJSON(data []byte) (err error) { - return apijson.UnmarshalRoot(data, r) -} - -func (r messageMetadataJSON) RawJSON() string { - return r.raw -} - -type MessageMetadataTime struct { - Created float64 `json:"created,required"` - Completed float64 `json:"completed"` - JSON messageMetadataTimeJSON `json:"-"` -} - -// messageMetadataTimeJSON contains the JSON metadata for the struct -// [MessageMetadataTime] -type messageMetadataTimeJSON struct { - Created apijson.Field - Completed apijson.Field + Summary apijson.Field raw string ExtraFields map[string]apijson.Field } -func (r *MessageMetadataTime) UnmarshalJSON(data []byte) (err error) { +func (r *AssistantMessage) UnmarshalJSON(data []byte) (err error) { return apijson.UnmarshalRoot(data, r) } -func (r messageMetadataTimeJSON) RawJSON() string { +func (r assistantMessageJSON) RawJSON() string { return r.raw } -type MessageMetadataTool struct { - Time MessageMetadataToolTime `json:"time,required"` - Title string `json:"title,required"` - Snapshot string `json:"snapshot"` - ExtraFields map[string]interface{} `json:"-,extras"` - JSON messageMetadataToolJSON `json:"-"` -} - -// messageMetadataToolJSON contains the JSON metadata for the struct -// [MessageMetadataTool] -type messageMetadataToolJSON struct { - Time apijson.Field - Title apijson.Field - Snapshot apijson.Field - raw string - ExtraFields map[string]apijson.Field -} +func (r AssistantMessage) implementsMessage() {} -func (r *MessageMetadataTool) UnmarshalJSON(data []byte) (err error) { - return apijson.UnmarshalRoot(data, r) +type AssistantMessagePath struct { + Cwd string `json:"cwd,required"` + Root string `json:"root,required"` + JSON assistantMessagePathJSON `json:"-"` } -func (r messageMetadataToolJSON) RawJSON() string { - return r.raw -} - -type MessageMetadataToolTime struct { - End float64 `json:"end,required"` - Start float64 `json:"start,required"` - JSON messageMetadataToolTimeJSON `json:"-"` -} - -// messageMetadataToolTimeJSON contains the JSON metadata for the struct -// [MessageMetadataToolTime] -type messageMetadataToolTimeJSON struct { - End apijson.Field - Start apijson.Field +// assistantMessagePathJSON contains the JSON metadata for the struct +// [AssistantMessagePath] +type assistantMessagePathJSON struct { + Cwd apijson.Field + Root apijson.Field raw string ExtraFields map[string]apijson.Field } -func (r *MessageMetadataToolTime) UnmarshalJSON(data []byte) (err error) { +func (r *AssistantMessagePath) UnmarshalJSON(data []byte) (err error) { return apijson.UnmarshalRoot(data, r) } -func (r messageMetadataToolTimeJSON) RawJSON() string { +func (r assistantMessagePathJSON) RawJSON() string { return r.raw } -type MessageMetadataAssistant struct { - Cost float64 `json:"cost,required"` - ModelID string `json:"modelID,required"` - Path MessageMetadataAssistantPath `json:"path,required"` - ProviderID string `json:"providerID,required"` - System []string `json:"system,required"` - Tokens MessageMetadataAssistantTokens `json:"tokens,required"` - Summary bool `json:"summary"` - JSON messageMetadataAssistantJSON `json:"-"` -} +type AssistantMessageRole string -// messageMetadataAssistantJSON contains the JSON metadata for the struct -// [MessageMetadataAssistant] -type messageMetadataAssistantJSON struct { - Cost apijson.Field - ModelID apijson.Field - Path apijson.Field - ProviderID apijson.Field - System apijson.Field - Tokens apijson.Field - Summary apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *MessageMetadataAssistant) UnmarshalJSON(data []byte) (err error) { - return apijson.UnmarshalRoot(data, r) -} +const ( + AssistantMessageRoleAssistant AssistantMessageRole = "assistant" +) -func (r messageMetadataAssistantJSON) RawJSON() string { - return r.raw +func (r AssistantMessageRole) IsKnown() bool { + switch r { + case AssistantMessageRoleAssistant: + return true + } + return false } -type MessageMetadataAssistantPath struct { - Cwd string `json:"cwd,required"` - Root string `json:"root,required"` - JSON messageMetadataAssistantPathJSON `json:"-"` +type AssistantMessageTime struct { + Created float64 `json:"created,required"` + Completed float64 `json:"completed"` + JSON assistantMessageTimeJSON `json:"-"` } -// messageMetadataAssistantPathJSON contains the JSON metadata for the struct -// [MessageMetadataAssistantPath] -type messageMetadataAssistantPathJSON struct { - Cwd apijson.Field - Root apijson.Field +// assistantMessageTimeJSON contains the JSON metadata for the struct +// [AssistantMessageTime] +type assistantMessageTimeJSON struct { + Created apijson.Field + Completed apijson.Field raw string ExtraFields map[string]apijson.Field } -func (r *MessageMetadataAssistantPath) UnmarshalJSON(data []byte) (err error) { +func (r *AssistantMessageTime) UnmarshalJSON(data []byte) (err error) { return apijson.UnmarshalRoot(data, r) } -func (r messageMetadataAssistantPathJSON) RawJSON() string { +func (r assistantMessageTimeJSON) RawJSON() string { return r.raw } -type MessageMetadataAssistantTokens struct { - Cache MessageMetadataAssistantTokensCache `json:"cache,required"` - Input float64 `json:"input,required"` - Output float64 `json:"output,required"` - Reasoning float64 `json:"reasoning,required"` - JSON messageMetadataAssistantTokensJSON `json:"-"` +type AssistantMessageTokens struct { + Cache AssistantMessageTokensCache `json:"cache,required"` + Input float64 `json:"input,required"` + Output float64 `json:"output,required"` + Reasoning float64 `json:"reasoning,required"` + JSON assistantMessageTokensJSON `json:"-"` } -// messageMetadataAssistantTokensJSON contains the JSON metadata for the struct -// [MessageMetadataAssistantTokens] -type messageMetadataAssistantTokensJSON struct { +// assistantMessageTokensJSON contains the JSON metadata for the struct +// [AssistantMessageTokens] +type assistantMessageTokensJSON struct { Cache apijson.Field Input apijson.Field Output apijson.Field @@ -406,61 +274,61 @@ type messageMetadataAssistantTokensJSON struct { ExtraFields map[string]apijson.Field } -func (r *MessageMetadataAssistantTokens) UnmarshalJSON(data []byte) (err error) { +func (r *AssistantMessageTokens) UnmarshalJSON(data []byte) (err error) { return apijson.UnmarshalRoot(data, r) } -func (r messageMetadataAssistantTokensJSON) RawJSON() string { +func (r assistantMessageTokensJSON) RawJSON() string { return r.raw } -type MessageMetadataAssistantTokensCache struct { - Read float64 `json:"read,required"` - Write float64 `json:"write,required"` - JSON messageMetadataAssistantTokensCacheJSON `json:"-"` +type AssistantMessageTokensCache struct { + Read float64 `json:"read,required"` + Write float64 `json:"write,required"` + JSON assistantMessageTokensCacheJSON `json:"-"` } -// messageMetadataAssistantTokensCacheJSON contains the JSON metadata for the -// struct [MessageMetadataAssistantTokensCache] -type messageMetadataAssistantTokensCacheJSON struct { +// assistantMessageTokensCacheJSON contains the JSON metadata for the struct +// [AssistantMessageTokensCache] +type assistantMessageTokensCacheJSON struct { Read apijson.Field Write apijson.Field raw string ExtraFields map[string]apijson.Field } -func (r *MessageMetadataAssistantTokensCache) UnmarshalJSON(data []byte) (err error) { +func (r *AssistantMessageTokensCache) UnmarshalJSON(data []byte) (err error) { return apijson.UnmarshalRoot(data, r) } -func (r messageMetadataAssistantTokensCacheJSON) RawJSON() string { +func (r assistantMessageTokensCacheJSON) RawJSON() string { return r.raw } -type MessageMetadataError struct { +type AssistantMessageError struct { // This field can have the runtime type of [shared.ProviderAuthErrorData], // [shared.UnknownErrorData], [interface{}]. - Data interface{} `json:"data,required"` - Name MessageMetadataErrorName `json:"name,required"` - JSON messageMetadataErrorJSON `json:"-"` - union MessageMetadataErrorUnion + Data interface{} `json:"data,required"` + Name AssistantMessageErrorName `json:"name,required"` + JSON assistantMessageErrorJSON `json:"-"` + union AssistantMessageErrorUnion } -// messageMetadataErrorJSON contains the JSON metadata for the struct -// [MessageMetadataError] -type messageMetadataErrorJSON struct { +// assistantMessageErrorJSON contains the JSON metadata for the struct +// [AssistantMessageError] +type assistantMessageErrorJSON struct { Data apijson.Field Name apijson.Field raw string ExtraFields map[string]apijson.Field } -func (r messageMetadataErrorJSON) RawJSON() string { +func (r assistantMessageErrorJSON) RawJSON() string { return r.raw } -func (r *MessageMetadataError) UnmarshalJSON(data []byte) (err error) { - *r = MessageMetadataError{} +func (r *AssistantMessageError) UnmarshalJSON(data []byte) (err error) { + *r = AssistantMessageError{} err = apijson.UnmarshalRoot(data, &r.union) if err != nil { return err @@ -468,24 +336,24 @@ func (r *MessageMetadataError) UnmarshalJSON(data []byte) (err error) { return apijson.Port(r.union, &r) } -// AsUnion returns a [MessageMetadataErrorUnion] interface which you can cast to +// AsUnion returns a [AssistantMessageErrorUnion] interface which you can cast to // the specific types for more type safety. // // Possible runtime types of the union are [shared.ProviderAuthError], -// [shared.UnknownError], [MessageMetadataErrorMessageOutputLengthError]. -func (r MessageMetadataError) AsUnion() MessageMetadataErrorUnion { +// [shared.UnknownError], [AssistantMessageErrorMessageOutputLengthError]. +func (r AssistantMessageError) AsUnion() AssistantMessageErrorUnion { return r.union } // Union satisfied by [shared.ProviderAuthError], [shared.UnknownError] or -// [MessageMetadataErrorMessageOutputLengthError]. -type MessageMetadataErrorUnion interface { - ImplementsMessageMetadataError() +// [AssistantMessageErrorMessageOutputLengthError]. +type AssistantMessageErrorUnion interface { + ImplementsAssistantMessageError() } func init() { apijson.RegisterUnion( - reflect.TypeOf((*MessageMetadataErrorUnion)(nil)).Elem(), + reflect.TypeOf((*AssistantMessageErrorUnion)(nil)).Elem(), "name", apijson.UnionVariant{ TypeFilter: gjson.JSON, @@ -499,119 +367,96 @@ func init() { }, apijson.UnionVariant{ TypeFilter: gjson.JSON, - Type: reflect.TypeOf(MessageMetadataErrorMessageOutputLengthError{}), + Type: reflect.TypeOf(AssistantMessageErrorMessageOutputLengthError{}), DiscriminatorValue: "MessageOutputLengthError", }, ) } -type MessageMetadataErrorMessageOutputLengthError struct { - Data interface{} `json:"data,required"` - Name MessageMetadataErrorMessageOutputLengthErrorName `json:"name,required"` - JSON messageMetadataErrorMessageOutputLengthErrorJSON `json:"-"` +type AssistantMessageErrorMessageOutputLengthError struct { + Data interface{} `json:"data,required"` + Name AssistantMessageErrorMessageOutputLengthErrorName `json:"name,required"` + JSON assistantMessageErrorMessageOutputLengthErrorJSON `json:"-"` } -// messageMetadataErrorMessageOutputLengthErrorJSON contains the JSON metadata for -// the struct [MessageMetadataErrorMessageOutputLengthError] -type messageMetadataErrorMessageOutputLengthErrorJSON struct { +// assistantMessageErrorMessageOutputLengthErrorJSON contains the JSON metadata for +// the struct [AssistantMessageErrorMessageOutputLengthError] +type assistantMessageErrorMessageOutputLengthErrorJSON struct { Data apijson.Field Name apijson.Field raw string ExtraFields map[string]apijson.Field } -func (r *MessageMetadataErrorMessageOutputLengthError) UnmarshalJSON(data []byte) (err error) { +func (r *AssistantMessageErrorMessageOutputLengthError) UnmarshalJSON(data []byte) (err error) { return apijson.UnmarshalRoot(data, r) } -func (r messageMetadataErrorMessageOutputLengthErrorJSON) RawJSON() string { +func (r assistantMessageErrorMessageOutputLengthErrorJSON) RawJSON() string { return r.raw } -func (r MessageMetadataErrorMessageOutputLengthError) ImplementsMessageMetadataError() {} +func (r AssistantMessageErrorMessageOutputLengthError) ImplementsAssistantMessageError() {} -type MessageMetadataErrorMessageOutputLengthErrorName string +type AssistantMessageErrorMessageOutputLengthErrorName string const ( - MessageMetadataErrorMessageOutputLengthErrorNameMessageOutputLengthError MessageMetadataErrorMessageOutputLengthErrorName = "MessageOutputLengthError" + AssistantMessageErrorMessageOutputLengthErrorNameMessageOutputLengthError AssistantMessageErrorMessageOutputLengthErrorName = "MessageOutputLengthError" ) -func (r MessageMetadataErrorMessageOutputLengthErrorName) IsKnown() bool { +func (r AssistantMessageErrorMessageOutputLengthErrorName) IsKnown() bool { switch r { - case MessageMetadataErrorMessageOutputLengthErrorNameMessageOutputLengthError: + case AssistantMessageErrorMessageOutputLengthErrorNameMessageOutputLengthError: return true } return false } -type MessageMetadataErrorName string +type AssistantMessageErrorName string const ( - MessageMetadataErrorNameProviderAuthError MessageMetadataErrorName = "ProviderAuthError" - MessageMetadataErrorNameUnknownError MessageMetadataErrorName = "UnknownError" - MessageMetadataErrorNameMessageOutputLengthError MessageMetadataErrorName = "MessageOutputLengthError" + AssistantMessageErrorNameProviderAuthError AssistantMessageErrorName = "ProviderAuthError" + AssistantMessageErrorNameUnknownError AssistantMessageErrorName = "UnknownError" + AssistantMessageErrorNameMessageOutputLengthError AssistantMessageErrorName = "MessageOutputLengthError" ) -func (r MessageMetadataErrorName) IsKnown() bool { +func (r AssistantMessageErrorName) IsKnown() bool { switch r { - case MessageMetadataErrorNameProviderAuthError, MessageMetadataErrorNameUnknownError, MessageMetadataErrorNameMessageOutputLengthError: + case AssistantMessageErrorNameProviderAuthError, AssistantMessageErrorNameUnknownError, AssistantMessageErrorNameMessageOutputLengthError: return true } return false } -type MessageRole string - -const ( - MessageRoleUser MessageRole = "user" - MessageRoleAssistant MessageRole = "assistant" -) +type AssistantMessagePart struct { + Type AssistantMessagePartType `json:"type,required"` + ID string `json:"id"` + // This field can have the runtime type of [ToolPartState]. + State interface{} `json:"state"` + Text string `json:"text"` + Tool string `json:"tool"` + JSON assistantMessagePartJSON `json:"-"` + union AssistantMessagePartUnion +} -func (r MessageRole) IsKnown() bool { - switch r { - case MessageRoleUser, MessageRoleAssistant: - return true - } - return false +// assistantMessagePartJSON contains the JSON metadata for the struct +// [AssistantMessagePart] +type assistantMessagePartJSON struct { + Type apijson.Field + ID apijson.Field + State apijson.Field + Text apijson.Field + Tool apijson.Field + raw string + ExtraFields map[string]apijson.Field } -type MessagePart struct { - Type MessagePartType `json:"type,required"` - Filename string `json:"filename"` - MediaType string `json:"mediaType"` - // This field can have the runtime type of [map[string]interface{}]. - ProviderMetadata interface{} `json:"providerMetadata"` - SourceID string `json:"sourceId"` - Text string `json:"text"` - Title string `json:"title"` - // This field can have the runtime type of [ToolInvocationPartToolInvocation]. - ToolInvocation interface{} `json:"toolInvocation"` - URL string `json:"url"` - JSON messagePartJSON `json:"-"` - union MessagePartUnion -} - -// messagePartJSON contains the JSON metadata for the struct [MessagePart] -type messagePartJSON struct { - Type apijson.Field - Filename apijson.Field - MediaType apijson.Field - ProviderMetadata apijson.Field - SourceID apijson.Field - Text apijson.Field - Title apijson.Field - ToolInvocation apijson.Field - URL apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r messagePartJSON) RawJSON() string { +func (r assistantMessagePartJSON) RawJSON() string { return r.raw } -func (r *MessagePart) UnmarshalJSON(data []byte) (err error) { - *r = MessagePart{} +func (r *AssistantMessagePart) UnmarshalJSON(data []byte) (err error) { + *r = AssistantMessagePart{} err = apijson.UnmarshalRoot(data, &r.union) if err != nil { return err @@ -619,24 +464,22 @@ func (r *MessagePart) UnmarshalJSON(data []byte) (err error) { return apijson.Port(r.union, &r) } -// AsUnion returns a [MessagePartUnion] interface which you can cast to the -// specific types for more type safety. +// AsUnion returns a [AssistantMessagePartUnion] interface which you can cast to +// the specific types for more type safety. // -// Possible runtime types of the union are [TextPart], [ReasoningPart], -// [ToolInvocationPart], [SourceURLPart], [FilePart], [StepStartPart]. -func (r MessagePart) AsUnion() MessagePartUnion { +// Possible runtime types of the union are [TextPart], [ToolPart], [StepStartPart]. +func (r AssistantMessagePart) AsUnion() AssistantMessagePartUnion { return r.union } -// Union satisfied by [TextPart], [ReasoningPart], [ToolInvocationPart], -// [SourceURLPart], [FilePart] or [StepStartPart]. -type MessagePartUnion interface { - implementsMessagePart() +// Union satisfied by [TextPart], [ToolPart] or [StepStartPart]. +type AssistantMessagePartUnion interface { + implementsAssistantMessagePart() } func init() { apijson.RegisterUnion( - reflect.TypeOf((*MessagePartUnion)(nil)).Elem(), + reflect.TypeOf((*AssistantMessagePartUnion)(nil)).Elem(), "type", apijson.UnionVariant{ TypeFilter: gjson.JSON, @@ -645,23 +488,8 @@ func init() { }, apijson.UnionVariant{ TypeFilter: gjson.JSON, - Type: reflect.TypeOf(ReasoningPart{}), - DiscriminatorValue: "reasoning", - }, - apijson.UnionVariant{ - TypeFilter: gjson.JSON, - Type: reflect.TypeOf(ToolInvocationPart{}), - DiscriminatorValue: "tool-invocation", - }, - apijson.UnionVariant{ - TypeFilter: gjson.JSON, - Type: reflect.TypeOf(SourceURLPart{}), - DiscriminatorValue: "source-url", - }, - apijson.UnionVariant{ - TypeFilter: gjson.JSON, - Type: reflect.TypeOf(FilePart{}), - DiscriminatorValue: "file", + Type: reflect.TypeOf(ToolPart{}), + DiscriminatorValue: "tool", }, apijson.UnionVariant{ TypeFilter: gjson.JSON, @@ -671,100 +499,179 @@ func init() { ) } -type MessagePartType string +type AssistantMessagePartType string const ( - MessagePartTypeText MessagePartType = "text" - MessagePartTypeReasoning MessagePartType = "reasoning" - MessagePartTypeToolInvocation MessagePartType = "tool-invocation" - MessagePartTypeSourceURL MessagePartType = "source-url" - MessagePartTypeFile MessagePartType = "file" - MessagePartTypeStepStart MessagePartType = "step-start" + AssistantMessagePartTypeText AssistantMessagePartType = "text" + AssistantMessagePartTypeTool AssistantMessagePartType = "tool" + AssistantMessagePartTypeStepStart AssistantMessagePartType = "step-start" ) -func (r MessagePartType) IsKnown() bool { +func (r AssistantMessagePartType) IsKnown() bool { switch r { - case MessagePartTypeText, MessagePartTypeReasoning, MessagePartTypeToolInvocation, MessagePartTypeSourceURL, MessagePartTypeFile, MessagePartTypeStepStart: + case AssistantMessagePartTypeText, AssistantMessagePartTypeTool, AssistantMessagePartTypeStepStart: return true } return false } -type MessagePartParam struct { - Type param.Field[MessagePartType] `json:"type,required"` - Filename param.Field[string] `json:"filename"` - MediaType param.Field[string] `json:"mediaType"` - ProviderMetadata param.Field[interface{}] `json:"providerMetadata"` - SourceID param.Field[string] `json:"sourceId"` - Text param.Field[string] `json:"text"` - Title param.Field[string] `json:"title"` - ToolInvocation param.Field[interface{}] `json:"toolInvocation"` - URL param.Field[string] `json:"url"` -} - -func (r MessagePartParam) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) -} - -func (r MessagePartParam) implementsMessagePartUnionParam() {} - -// Satisfied by [TextPartParam], [ReasoningPartParam], [ToolInvocationPartParam], -// [SourceURLPartParam], [FilePartParam], [StepStartPartParam], [MessagePartParam]. -type MessagePartUnionParam interface { - implementsMessagePartUnionParam() -} - -type ReasoningPart struct { - Text string `json:"text,required"` - Type ReasoningPartType `json:"type,required"` - ProviderMetadata map[string]interface{} `json:"providerMetadata"` - JSON reasoningPartJSON `json:"-"` +type FilePart struct { + Mime string `json:"mime,required"` + Type FilePartType `json:"type,required"` + URL string `json:"url,required"` + Filename string `json:"filename"` + JSON filePartJSON `json:"-"` } -// reasoningPartJSON contains the JSON metadata for the struct [ReasoningPart] -type reasoningPartJSON struct { - Text apijson.Field - Type apijson.Field - ProviderMetadata apijson.Field - raw string - ExtraFields map[string]apijson.Field +// filePartJSON contains the JSON metadata for the struct [FilePart] +type filePartJSON struct { + Mime apijson.Field + Type apijson.Field + URL apijson.Field + Filename apijson.Field + raw string + ExtraFields map[string]apijson.Field } -func (r *ReasoningPart) UnmarshalJSON(data []byte) (err error) { +func (r *FilePart) UnmarshalJSON(data []byte) (err error) { return apijson.UnmarshalRoot(data, r) } -func (r reasoningPartJSON) RawJSON() string { +func (r filePartJSON) RawJSON() string { return r.raw } -func (r ReasoningPart) implementsMessagePart() {} +func (r FilePart) implementsUserMessagePart() {} -type ReasoningPartType string +type FilePartType string const ( - ReasoningPartTypeReasoning ReasoningPartType = "reasoning" + FilePartTypeFile FilePartType = "file" ) -func (r ReasoningPartType) IsKnown() bool { +func (r FilePartType) IsKnown() bool { switch r { - case ReasoningPartTypeReasoning: + case FilePartTypeFile: return true } return false } -type ReasoningPartParam struct { - Text param.Field[string] `json:"text,required"` - Type param.Field[ReasoningPartType] `json:"type,required"` - ProviderMetadata param.Field[map[string]interface{}] `json:"providerMetadata"` +type FilePartParam struct { + Mime param.Field[string] `json:"mime,required"` + Type param.Field[FilePartType] `json:"type,required"` + URL param.Field[string] `json:"url,required"` + Filename param.Field[string] `json:"filename"` } -func (r ReasoningPartParam) MarshalJSON() (data []byte, err error) { +func (r FilePartParam) MarshalJSON() (data []byte, err error) { return apijson.MarshalRoot(r) } -func (r ReasoningPartParam) implementsMessagePartUnionParam() {} +func (r FilePartParam) implementsUserMessagePartUnionParam() {} + +type Message struct { + ID string `json:"id,required"` + // This field can have the runtime type of [[]UserMessagePart], + // [[]AssistantMessagePart]. + Parts interface{} `json:"parts,required"` + Role MessageRole `json:"role,required"` + SessionID string `json:"sessionID,required"` + // This field can have the runtime type of [UserMessageTime], + // [AssistantMessageTime]. + Time interface{} `json:"time,required"` + Cost float64 `json:"cost"` + // This field can have the runtime type of [AssistantMessageError]. + Error interface{} `json:"error"` + ModelID string `json:"modelID"` + // This field can have the runtime type of [AssistantMessagePath]. + Path interface{} `json:"path"` + ProviderID string `json:"providerID"` + Summary bool `json:"summary"` + // This field can have the runtime type of [[]string]. + System interface{} `json:"system"` + // This field can have the runtime type of [AssistantMessageTokens]. + Tokens interface{} `json:"tokens"` + JSON messageJSON `json:"-"` + union MessageUnion +} + +// messageJSON contains the JSON metadata for the struct [Message] +type messageJSON struct { + ID apijson.Field + Parts apijson.Field + Role apijson.Field + SessionID apijson.Field + Time apijson.Field + Cost apijson.Field + Error apijson.Field + ModelID apijson.Field + Path apijson.Field + ProviderID apijson.Field + Summary apijson.Field + System apijson.Field + Tokens apijson.Field + raw string + ExtraFields map[string]apijson.Field +} + +func (r messageJSON) RawJSON() string { + return r.raw +} + +func (r *Message) UnmarshalJSON(data []byte) (err error) { + *r = Message{} + err = apijson.UnmarshalRoot(data, &r.union) + if err != nil { + return err + } + return apijson.Port(r.union, &r) +} + +// AsUnion returns a [MessageUnion] interface which you can cast to the specific +// types for more type safety. +// +// Possible runtime types of the union are [UserMessage], [AssistantMessage]. +func (r Message) AsUnion() MessageUnion { + return r.union +} + +// Union satisfied by [UserMessage] or [AssistantMessage]. +type MessageUnion interface { + implementsMessage() +} + +func init() { + apijson.RegisterUnion( + reflect.TypeOf((*MessageUnion)(nil)).Elem(), + "role", + apijson.UnionVariant{ + TypeFilter: gjson.JSON, + Type: reflect.TypeOf(UserMessage{}), + DiscriminatorValue: "user", + }, + apijson.UnionVariant{ + TypeFilter: gjson.JSON, + Type: reflect.TypeOf(AssistantMessage{}), + DiscriminatorValue: "assistant", + }, + ) +} + +type MessageRole string + +const ( + MessageRoleUser MessageRole = "user" + MessageRoleAssistant MessageRole = "assistant" +) + +func (r MessageRole) IsKnown() bool { + switch r { + case MessageRoleUser, MessageRoleAssistant: + return true + } + return false +} type Session struct { ID string `json:"id,required"` @@ -864,64 +771,6 @@ func (r sessionShareJSON) RawJSON() string { return r.raw } -type SourceURLPart struct { - SourceID string `json:"sourceId,required"` - Type SourceURLPartType `json:"type,required"` - URL string `json:"url,required"` - ProviderMetadata map[string]interface{} `json:"providerMetadata"` - Title string `json:"title"` - JSON sourceURLPartJSON `json:"-"` -} - -// sourceURLPartJSON contains the JSON metadata for the struct [SourceURLPart] -type sourceURLPartJSON struct { - SourceID apijson.Field - Type apijson.Field - URL apijson.Field - ProviderMetadata apijson.Field - Title apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *SourceURLPart) UnmarshalJSON(data []byte) (err error) { - return apijson.UnmarshalRoot(data, r) -} - -func (r sourceURLPartJSON) RawJSON() string { - return r.raw -} - -func (r SourceURLPart) implementsMessagePart() {} - -type SourceURLPartType string - -const ( - SourceURLPartTypeSourceURL SourceURLPartType = "source-url" -) - -func (r SourceURLPartType) IsKnown() bool { - switch r { - case SourceURLPartTypeSourceURL: - return true - } - return false -} - -type SourceURLPartParam struct { - SourceID param.Field[string] `json:"sourceId,required"` - Type param.Field[SourceURLPartType] `json:"type,required"` - URL param.Field[string] `json:"url,required"` - ProviderMetadata param.Field[map[string]interface{}] `json:"providerMetadata"` - Title param.Field[string] `json:"title"` -} - -func (r SourceURLPartParam) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) -} - -func (r SourceURLPartParam) implementsMessagePartUnionParam() {} - type StepStartPart struct { Type StepStartPartType `json:"type,required"` JSON stepStartPartJSON `json:"-"` @@ -942,7 +791,7 @@ func (r stepStartPartJSON) RawJSON() string { return r.raw } -func (r StepStartPart) implementsMessagePart() {} +func (r StepStartPart) implementsAssistantMessagePart() {} type StepStartPartType string @@ -958,16 +807,6 @@ func (r StepStartPartType) IsKnown() bool { return false } -type StepStartPartParam struct { - Type param.Field[StepStartPartType] `json:"type,required"` -} - -func (r StepStartPartParam) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) -} - -func (r StepStartPartParam) implementsMessagePartUnionParam() {} - type TextPart struct { Text string `json:"text,required"` Type TextPartType `json:"type,required"` @@ -990,7 +829,9 @@ func (r textPartJSON) RawJSON() string { return r.raw } -func (r TextPart) implementsMessagePart() {} +func (r TextPart) implementsAssistantMessagePart() {} + +func (r TextPart) implementsUserMessagePart() {} type TextPartType string @@ -1015,351 +856,555 @@ func (r TextPartParam) MarshalJSON() (data []byte, err error) { return apijson.MarshalRoot(r) } -func (r TextPartParam) implementsMessagePartUnionParam() {} +func (r TextPartParam) implementsUserMessagePartUnionParam() {} -type ToolCall struct { - State ToolCallState `json:"state,required"` - ToolCallID string `json:"toolCallId,required"` - ToolName string `json:"toolName,required"` - Args interface{} `json:"args"` - Step float64 `json:"step"` - JSON toolCallJSON `json:"-"` +type ToolPart struct { + ID string `json:"id,required"` + State ToolPartState `json:"state,required"` + Tool string `json:"tool,required"` + Type ToolPartType `json:"type,required"` + JSON toolPartJSON `json:"-"` } -// toolCallJSON contains the JSON metadata for the struct [ToolCall] -type toolCallJSON struct { +// toolPartJSON contains the JSON metadata for the struct [ToolPart] +type toolPartJSON struct { + ID apijson.Field State apijson.Field - ToolCallID apijson.Field - ToolName apijson.Field - Args apijson.Field - Step apijson.Field + Tool apijson.Field + Type apijson.Field raw string ExtraFields map[string]apijson.Field } -func (r *ToolCall) UnmarshalJSON(data []byte) (err error) { +func (r *ToolPart) UnmarshalJSON(data []byte) (err error) { return apijson.UnmarshalRoot(data, r) } -func (r toolCallJSON) RawJSON() string { +func (r toolPartJSON) RawJSON() string { return r.raw } -func (r ToolCall) implementsToolInvocationPartToolInvocation() {} +func (r ToolPart) implementsAssistantMessagePart() {} + +type ToolPartState struct { + Status ToolPartStateStatus `json:"status,required"` + Error string `json:"error"` + // This field can have the runtime type of [interface{}]. + Input interface{} `json:"input"` + // This field can have the runtime type of [map[string]interface{}]. + Metadata interface{} `json:"metadata"` + Output string `json:"output"` + // This field can have the runtime type of [ToolStateRunningTime], + // [ToolStateCompletedTime], [ToolStateErrorTime]. + Time interface{} `json:"time"` + Title string `json:"title"` + JSON toolPartStateJSON `json:"-"` + union ToolPartStateUnion +} + +// toolPartStateJSON contains the JSON metadata for the struct [ToolPartState] +type toolPartStateJSON struct { + Status apijson.Field + Error apijson.Field + Input apijson.Field + Metadata apijson.Field + Output apijson.Field + Time apijson.Field + Title apijson.Field + raw string + ExtraFields map[string]apijson.Field +} + +func (r toolPartStateJSON) RawJSON() string { + return r.raw +} + +func (r *ToolPartState) UnmarshalJSON(data []byte) (err error) { + *r = ToolPartState{} + err = apijson.UnmarshalRoot(data, &r.union) + if err != nil { + return err + } + return apijson.Port(r.union, &r) +} + +// AsUnion returns a [ToolPartStateUnion] interface which you can cast to the +// specific types for more type safety. +// +// Possible runtime types of the union are [ToolStatePending], [ToolStateRunning], +// [ToolStateCompleted], [ToolStateError]. +func (r ToolPartState) AsUnion() ToolPartStateUnion { + return r.union +} + +// Union satisfied by [ToolStatePending], [ToolStateRunning], [ToolStateCompleted] +// or [ToolStateError]. +type ToolPartStateUnion interface { + implementsToolPartState() +} + +func init() { + apijson.RegisterUnion( + reflect.TypeOf((*ToolPartStateUnion)(nil)).Elem(), + "status", + apijson.UnionVariant{ + TypeFilter: gjson.JSON, + Type: reflect.TypeOf(ToolStatePending{}), + DiscriminatorValue: "pending", + }, + apijson.UnionVariant{ + TypeFilter: gjson.JSON, + Type: reflect.TypeOf(ToolStateRunning{}), + DiscriminatorValue: "running", + }, + apijson.UnionVariant{ + TypeFilter: gjson.JSON, + Type: reflect.TypeOf(ToolStateCompleted{}), + DiscriminatorValue: "completed", + }, + apijson.UnionVariant{ + TypeFilter: gjson.JSON, + Type: reflect.TypeOf(ToolStateError{}), + DiscriminatorValue: "error", + }, + ) +} -type ToolCallState string +type ToolPartStateStatus string const ( - ToolCallStateCall ToolCallState = "call" + ToolPartStateStatusPending ToolPartStateStatus = "pending" + ToolPartStateStatusRunning ToolPartStateStatus = "running" + ToolPartStateStatusCompleted ToolPartStateStatus = "completed" + ToolPartStateStatusError ToolPartStateStatus = "error" ) -func (r ToolCallState) IsKnown() bool { +func (r ToolPartStateStatus) IsKnown() bool { switch r { - case ToolCallStateCall: + case ToolPartStateStatusPending, ToolPartStateStatusRunning, ToolPartStateStatusCompleted, ToolPartStateStatusError: return true } return false } -type ToolCallParam struct { - State param.Field[ToolCallState] `json:"state,required"` - ToolCallID param.Field[string] `json:"toolCallId,required"` - ToolName param.Field[string] `json:"toolName,required"` - Args param.Field[interface{}] `json:"args"` - Step param.Field[float64] `json:"step"` -} +type ToolPartType string -func (r ToolCallParam) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) -} +const ( + ToolPartTypeTool ToolPartType = "tool" +) -func (r ToolCallParam) implementsToolInvocationPartToolInvocationUnionParam() {} +func (r ToolPartType) IsKnown() bool { + switch r { + case ToolPartTypeTool: + return true + } + return false +} -type ToolInvocationPart struct { - ToolInvocation ToolInvocationPartToolInvocation `json:"toolInvocation,required"` - Type ToolInvocationPartType `json:"type,required"` - JSON toolInvocationPartJSON `json:"-"` +type ToolStateCompleted struct { + Metadata map[string]interface{} `json:"metadata,required"` + Output string `json:"output,required"` + Status ToolStateCompletedStatus `json:"status,required"` + Time ToolStateCompletedTime `json:"time,required"` + Title string `json:"title,required"` + Input interface{} `json:"input"` + JSON toolStateCompletedJSON `json:"-"` } -// toolInvocationPartJSON contains the JSON metadata for the struct -// [ToolInvocationPart] -type toolInvocationPartJSON struct { - ToolInvocation apijson.Field - Type apijson.Field - raw string - ExtraFields map[string]apijson.Field +// toolStateCompletedJSON contains the JSON metadata for the struct +// [ToolStateCompleted] +type toolStateCompletedJSON struct { + Metadata apijson.Field + Output apijson.Field + Status apijson.Field + Time apijson.Field + Title apijson.Field + Input apijson.Field + raw string + ExtraFields map[string]apijson.Field } -func (r *ToolInvocationPart) UnmarshalJSON(data []byte) (err error) { +func (r *ToolStateCompleted) UnmarshalJSON(data []byte) (err error) { return apijson.UnmarshalRoot(data, r) } -func (r toolInvocationPartJSON) RawJSON() string { +func (r toolStateCompletedJSON) RawJSON() string { return r.raw } -func (r ToolInvocationPart) implementsMessagePart() {} +func (r ToolStateCompleted) implementsToolPartState() {} -type ToolInvocationPartToolInvocation struct { - State ToolInvocationPartToolInvocationState `json:"state,required"` - ToolCallID string `json:"toolCallId,required"` - ToolName string `json:"toolName,required"` - // This field can have the runtime type of [interface{}]. - Args interface{} `json:"args"` - Result string `json:"result"` - Step float64 `json:"step"` - JSON toolInvocationPartToolInvocationJSON `json:"-"` - union ToolInvocationPartToolInvocationUnion +type ToolStateCompletedStatus string + +const ( + ToolStateCompletedStatusCompleted ToolStateCompletedStatus = "completed" +) + +func (r ToolStateCompletedStatus) IsKnown() bool { + switch r { + case ToolStateCompletedStatusCompleted: + return true + } + return false } -// toolInvocationPartToolInvocationJSON contains the JSON metadata for the struct -// [ToolInvocationPartToolInvocation] -type toolInvocationPartToolInvocationJSON struct { - State apijson.Field - ToolCallID apijson.Field - ToolName apijson.Field - Args apijson.Field - Result apijson.Field - Step apijson.Field +type ToolStateCompletedTime struct { + End float64 `json:"end,required"` + Start float64 `json:"start,required"` + JSON toolStateCompletedTimeJSON `json:"-"` +} + +// toolStateCompletedTimeJSON contains the JSON metadata for the struct +// [ToolStateCompletedTime] +type toolStateCompletedTimeJSON struct { + End apijson.Field + Start apijson.Field raw string ExtraFields map[string]apijson.Field } -func (r toolInvocationPartToolInvocationJSON) RawJSON() string { +func (r *ToolStateCompletedTime) UnmarshalJSON(data []byte) (err error) { + return apijson.UnmarshalRoot(data, r) +} + +func (r toolStateCompletedTimeJSON) RawJSON() string { return r.raw } -func (r *ToolInvocationPartToolInvocation) UnmarshalJSON(data []byte) (err error) { - *r = ToolInvocationPartToolInvocation{} - err = apijson.UnmarshalRoot(data, &r.union) - if err != nil { - return err - } - return apijson.Port(r.union, &r) +type ToolStateError struct { + Error string `json:"error,required"` + Status ToolStateErrorStatus `json:"status,required"` + Time ToolStateErrorTime `json:"time,required"` + Input interface{} `json:"input"` + JSON toolStateErrorJSON `json:"-"` } -// AsUnion returns a [ToolInvocationPartToolInvocationUnion] interface which you -// can cast to the specific types for more type safety. -// -// Possible runtime types of the union are [ToolCall], [ToolPartialCall], -// [ToolResult]. -func (r ToolInvocationPartToolInvocation) AsUnion() ToolInvocationPartToolInvocationUnion { - return r.union +// toolStateErrorJSON contains the JSON metadata for the struct [ToolStateError] +type toolStateErrorJSON struct { + Error apijson.Field + Status apijson.Field + Time apijson.Field + Input apijson.Field + raw string + ExtraFields map[string]apijson.Field } -// Union satisfied by [ToolCall], [ToolPartialCall] or [ToolResult]. -type ToolInvocationPartToolInvocationUnion interface { - implementsToolInvocationPartToolInvocation() +func (r *ToolStateError) UnmarshalJSON(data []byte) (err error) { + return apijson.UnmarshalRoot(data, r) } -func init() { - apijson.RegisterUnion( - reflect.TypeOf((*ToolInvocationPartToolInvocationUnion)(nil)).Elem(), - "state", - apijson.UnionVariant{ - TypeFilter: gjson.JSON, - Type: reflect.TypeOf(ToolCall{}), - DiscriminatorValue: "call", - }, - apijson.UnionVariant{ - TypeFilter: gjson.JSON, - Type: reflect.TypeOf(ToolPartialCall{}), - DiscriminatorValue: "partial-call", - }, - apijson.UnionVariant{ - TypeFilter: gjson.JSON, - Type: reflect.TypeOf(ToolResult{}), - DiscriminatorValue: "result", - }, - ) +func (r toolStateErrorJSON) RawJSON() string { + return r.raw } -type ToolInvocationPartToolInvocationState string +func (r ToolStateError) implementsToolPartState() {} + +type ToolStateErrorStatus string const ( - ToolInvocationPartToolInvocationStateCall ToolInvocationPartToolInvocationState = "call" - ToolInvocationPartToolInvocationStatePartialCall ToolInvocationPartToolInvocationState = "partial-call" - ToolInvocationPartToolInvocationStateResult ToolInvocationPartToolInvocationState = "result" + ToolStateErrorStatusError ToolStateErrorStatus = "error" ) -func (r ToolInvocationPartToolInvocationState) IsKnown() bool { +func (r ToolStateErrorStatus) IsKnown() bool { switch r { - case ToolInvocationPartToolInvocationStateCall, ToolInvocationPartToolInvocationStatePartialCall, ToolInvocationPartToolInvocationStateResult: + case ToolStateErrorStatusError: return true } return false } -type ToolInvocationPartType string +type ToolStateErrorTime struct { + End float64 `json:"end,required"` + Start float64 `json:"start,required"` + JSON toolStateErrorTimeJSON `json:"-"` +} + +// toolStateErrorTimeJSON contains the JSON metadata for the struct +// [ToolStateErrorTime] +type toolStateErrorTimeJSON struct { + End apijson.Field + Start apijson.Field + raw string + ExtraFields map[string]apijson.Field +} + +func (r *ToolStateErrorTime) UnmarshalJSON(data []byte) (err error) { + return apijson.UnmarshalRoot(data, r) +} + +func (r toolStateErrorTimeJSON) RawJSON() string { + return r.raw +} + +type ToolStatePending struct { + Status ToolStatePendingStatus `json:"status,required"` + JSON toolStatePendingJSON `json:"-"` +} + +// toolStatePendingJSON contains the JSON metadata for the struct +// [ToolStatePending] +type toolStatePendingJSON struct { + Status apijson.Field + raw string + ExtraFields map[string]apijson.Field +} + +func (r *ToolStatePending) UnmarshalJSON(data []byte) (err error) { + return apijson.UnmarshalRoot(data, r) +} + +func (r toolStatePendingJSON) RawJSON() string { + return r.raw +} + +func (r ToolStatePending) implementsToolPartState() {} + +type ToolStatePendingStatus string const ( - ToolInvocationPartTypeToolInvocation ToolInvocationPartType = "tool-invocation" + ToolStatePendingStatusPending ToolStatePendingStatus = "pending" ) -func (r ToolInvocationPartType) IsKnown() bool { +func (r ToolStatePendingStatus) IsKnown() bool { switch r { - case ToolInvocationPartTypeToolInvocation: + case ToolStatePendingStatusPending: return true } return false } -type ToolInvocationPartParam struct { - ToolInvocation param.Field[ToolInvocationPartToolInvocationUnionParam] `json:"toolInvocation,required"` - Type param.Field[ToolInvocationPartType] `json:"type,required"` +type ToolStateRunning struct { + Status ToolStateRunningStatus `json:"status,required"` + Time ToolStateRunningTime `json:"time,required"` + Input interface{} `json:"input"` + Metadata map[string]interface{} `json:"metadata"` + Title string `json:"title"` + JSON toolStateRunningJSON `json:"-"` } -func (r ToolInvocationPartParam) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) +// toolStateRunningJSON contains the JSON metadata for the struct +// [ToolStateRunning] +type toolStateRunningJSON struct { + Status apijson.Field + Time apijson.Field + Input apijson.Field + Metadata apijson.Field + Title apijson.Field + raw string + ExtraFields map[string]apijson.Field } -func (r ToolInvocationPartParam) implementsMessagePartUnionParam() {} +func (r *ToolStateRunning) UnmarshalJSON(data []byte) (err error) { + return apijson.UnmarshalRoot(data, r) +} -type ToolInvocationPartToolInvocationParam struct { - State param.Field[ToolInvocationPartToolInvocationState] `json:"state,required"` - ToolCallID param.Field[string] `json:"toolCallId,required"` - ToolName param.Field[string] `json:"toolName,required"` - Args param.Field[interface{}] `json:"args"` - Result param.Field[string] `json:"result"` - Step param.Field[float64] `json:"step"` +func (r toolStateRunningJSON) RawJSON() string { + return r.raw } -func (r ToolInvocationPartToolInvocationParam) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) +func (r ToolStateRunning) implementsToolPartState() {} + +type ToolStateRunningStatus string + +const ( + ToolStateRunningStatusRunning ToolStateRunningStatus = "running" +) + +func (r ToolStateRunningStatus) IsKnown() bool { + switch r { + case ToolStateRunningStatusRunning: + return true + } + return false } -func (r ToolInvocationPartToolInvocationParam) implementsToolInvocationPartToolInvocationUnionParam() { +type ToolStateRunningTime struct { + Start float64 `json:"start,required"` + JSON toolStateRunningTimeJSON `json:"-"` } -// Satisfied by [ToolCallParam], [ToolPartialCallParam], [ToolResultParam], -// [ToolInvocationPartToolInvocationParam]. -type ToolInvocationPartToolInvocationUnionParam interface { - implementsToolInvocationPartToolInvocationUnionParam() +// toolStateRunningTimeJSON contains the JSON metadata for the struct +// [ToolStateRunningTime] +type toolStateRunningTimeJSON struct { + Start apijson.Field + raw string + ExtraFields map[string]apijson.Field } -type ToolPartialCall struct { - State ToolPartialCallState `json:"state,required"` - ToolCallID string `json:"toolCallId,required"` - ToolName string `json:"toolName,required"` - Args interface{} `json:"args"` - Step float64 `json:"step"` - JSON toolPartialCallJSON `json:"-"` +func (r *ToolStateRunningTime) UnmarshalJSON(data []byte) (err error) { + return apijson.UnmarshalRoot(data, r) } -// toolPartialCallJSON contains the JSON metadata for the struct [ToolPartialCall] -type toolPartialCallJSON struct { - State apijson.Field - ToolCallID apijson.Field - ToolName apijson.Field - Args apijson.Field - Step apijson.Field +func (r toolStateRunningTimeJSON) RawJSON() string { + return r.raw +} + +type UserMessage struct { + ID string `json:"id,required"` + Parts []UserMessagePart `json:"parts,required"` + Role UserMessageRole `json:"role,required"` + SessionID string `json:"sessionID,required"` + Time UserMessageTime `json:"time,required"` + JSON userMessageJSON `json:"-"` +} + +// userMessageJSON contains the JSON metadata for the struct [UserMessage] +type userMessageJSON struct { + ID apijson.Field + Parts apijson.Field + Role apijson.Field + SessionID apijson.Field + Time apijson.Field raw string ExtraFields map[string]apijson.Field } -func (r *ToolPartialCall) UnmarshalJSON(data []byte) (err error) { +func (r *UserMessage) UnmarshalJSON(data []byte) (err error) { return apijson.UnmarshalRoot(data, r) } -func (r toolPartialCallJSON) RawJSON() string { +func (r userMessageJSON) RawJSON() string { return r.raw } -func (r ToolPartialCall) implementsToolInvocationPartToolInvocation() {} +func (r UserMessage) implementsMessage() {} -type ToolPartialCallState string +type UserMessageRole string const ( - ToolPartialCallStatePartialCall ToolPartialCallState = "partial-call" + UserMessageRoleUser UserMessageRole = "user" ) -func (r ToolPartialCallState) IsKnown() bool { +func (r UserMessageRole) IsKnown() bool { switch r { - case ToolPartialCallStatePartialCall: + case UserMessageRoleUser: return true } return false } -type ToolPartialCallParam struct { - State param.Field[ToolPartialCallState] `json:"state,required"` - ToolCallID param.Field[string] `json:"toolCallId,required"` - ToolName param.Field[string] `json:"toolName,required"` - Args param.Field[interface{}] `json:"args"` - Step param.Field[float64] `json:"step"` +type UserMessageTime struct { + Created float64 `json:"created,required"` + JSON userMessageTimeJSON `json:"-"` } -func (r ToolPartialCallParam) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) +// userMessageTimeJSON contains the JSON metadata for the struct [UserMessageTime] +type userMessageTimeJSON struct { + Created apijson.Field + raw string + ExtraFields map[string]apijson.Field +} + +func (r *UserMessageTime) UnmarshalJSON(data []byte) (err error) { + return apijson.UnmarshalRoot(data, r) } -func (r ToolPartialCallParam) implementsToolInvocationPartToolInvocationUnionParam() {} +func (r userMessageTimeJSON) RawJSON() string { + return r.raw +} -type ToolResult struct { - Result string `json:"result,required"` - State ToolResultState `json:"state,required"` - ToolCallID string `json:"toolCallId,required"` - ToolName string `json:"toolName,required"` - Args interface{} `json:"args"` - Step float64 `json:"step"` - JSON toolResultJSON `json:"-"` +type UserMessagePart struct { + Type UserMessagePartType `json:"type,required"` + Filename string `json:"filename"` + Mime string `json:"mime"` + Text string `json:"text"` + URL string `json:"url"` + JSON userMessagePartJSON `json:"-"` + union UserMessagePartUnion } -// toolResultJSON contains the JSON metadata for the struct [ToolResult] -type toolResultJSON struct { - Result apijson.Field - State apijson.Field - ToolCallID apijson.Field - ToolName apijson.Field - Args apijson.Field - Step apijson.Field +// userMessagePartJSON contains the JSON metadata for the struct [UserMessagePart] +type userMessagePartJSON struct { + Type apijson.Field + Filename apijson.Field + Mime apijson.Field + Text apijson.Field + URL apijson.Field raw string ExtraFields map[string]apijson.Field } -func (r *ToolResult) UnmarshalJSON(data []byte) (err error) { - return apijson.UnmarshalRoot(data, r) +func (r userMessagePartJSON) RawJSON() string { + return r.raw } -func (r toolResultJSON) RawJSON() string { - return r.raw +func (r *UserMessagePart) UnmarshalJSON(data []byte) (err error) { + *r = UserMessagePart{} + err = apijson.UnmarshalRoot(data, &r.union) + if err != nil { + return err + } + return apijson.Port(r.union, &r) } -func (r ToolResult) implementsToolInvocationPartToolInvocation() {} +// AsUnion returns a [UserMessagePartUnion] interface which you can cast to the +// specific types for more type safety. +// +// Possible runtime types of the union are [TextPart], [FilePart]. +func (r UserMessagePart) AsUnion() UserMessagePartUnion { + return r.union +} -type ToolResultState string +// Union satisfied by [TextPart] or [FilePart]. +type UserMessagePartUnion interface { + implementsUserMessagePart() +} + +func init() { + apijson.RegisterUnion( + reflect.TypeOf((*UserMessagePartUnion)(nil)).Elem(), + "type", + apijson.UnionVariant{ + TypeFilter: gjson.JSON, + Type: reflect.TypeOf(TextPart{}), + DiscriminatorValue: "text", + }, + apijson.UnionVariant{ + TypeFilter: gjson.JSON, + Type: reflect.TypeOf(FilePart{}), + DiscriminatorValue: "file", + }, + ) +} + +type UserMessagePartType string const ( - ToolResultStateResult ToolResultState = "result" + UserMessagePartTypeText UserMessagePartType = "text" + UserMessagePartTypeFile UserMessagePartType = "file" ) -func (r ToolResultState) IsKnown() bool { +func (r UserMessagePartType) IsKnown() bool { switch r { - case ToolResultStateResult: + case UserMessagePartTypeText, UserMessagePartTypeFile: return true } return false } -type ToolResultParam struct { - Result param.Field[string] `json:"result,required"` - State param.Field[ToolResultState] `json:"state,required"` - ToolCallID param.Field[string] `json:"toolCallId,required"` - ToolName param.Field[string] `json:"toolName,required"` - Args param.Field[interface{}] `json:"args"` - Step param.Field[float64] `json:"step"` +type UserMessagePartParam struct { + Type param.Field[UserMessagePartType] `json:"type,required"` + Filename param.Field[string] `json:"filename"` + Mime param.Field[string] `json:"mime"` + Text param.Field[string] `json:"text"` + URL param.Field[string] `json:"url"` } -func (r ToolResultParam) MarshalJSON() (data []byte, err error) { +func (r UserMessagePartParam) MarshalJSON() (data []byte, err error) { return apijson.MarshalRoot(r) } -func (r ToolResultParam) implementsToolInvocationPartToolInvocationUnionParam() {} +func (r UserMessagePartParam) implementsUserMessagePartUnionParam() {} + +// Satisfied by [TextPartParam], [FilePartParam], [UserMessagePartParam]. +type UserMessagePartUnionParam interface { + implementsUserMessagePartUnionParam() +} type SessionChatParams struct { - ModelID param.Field[string] `json:"modelID,required"` - Parts param.Field[[]MessagePartUnionParam] `json:"parts,required"` - ProviderID param.Field[string] `json:"providerID,required"` + ModelID param.Field[string] `json:"modelID,required"` + Parts param.Field[[]UserMessagePartUnionParam] `json:"parts,required"` + ProviderID param.Field[string] `json:"providerID,required"` } func (r SessionChatParams) MarshalJSON() (data []byte, err error) { diff --git a/packages/tui/sdk/session_test.go b/packages/tui/sdk/session_test.go index da9fb8252..15137e62c 100644 --- a/packages/tui/sdk/session_test.go +++ b/packages/tui/sdk/session_test.go @@ -118,7 +118,7 @@ func TestSessionChat(t *testing.T) { "id", opencode.SessionChatParams{ ModelID: opencode.F("modelID"), - Parts: opencode.F([]opencode.MessagePartUnionParam{opencode.TextPartParam{ + Parts: opencode.F([]opencode.UserMessagePartUnionParam{opencode.TextPartParam{ Text: opencode.F("text"), Type: opencode.F(opencode.TextPartTypeText), }}), diff --git a/packages/tui/sdk/shared/shared.go b/packages/tui/sdk/shared/shared.go index 121f64a5a..1ab53b6fa 100644 --- a/packages/tui/sdk/shared/shared.go +++ b/packages/tui/sdk/shared/shared.go @@ -31,7 +31,7 @@ func (r providerAuthErrorJSON) RawJSON() string { func (r ProviderAuthError) ImplementsEventListResponseEventSessionErrorPropertiesError() {} -func (r ProviderAuthError) ImplementsMessageMetadataError() {} +func (r ProviderAuthError) ImplementsAssistantMessageError() {} type ProviderAuthErrorData struct { Message string `json:"message,required"` @@ -94,7 +94,7 @@ func (r unknownErrorJSON) RawJSON() string { func (r UnknownError) ImplementsEventListResponseEventSessionErrorPropertiesError() {} -func (r UnknownError) ImplementsMessageMetadataError() {} +func (r UnknownError) ImplementsAssistantMessageError() {} type UnknownErrorData struct { Message string `json:"message,required"` |
