Просмотр исходного кода

feat(tui): optimistically render user messages

adamdottv 8 месяцев назад
Родитель
Сommit
8d3b2fb821

+ 46 - 44
packages/opencode/src/session/message.ts

@@ -135,53 +135,55 @@ export namespace Message {
       id: z.string(),
       role: z.enum(["user", "assistant"]),
       parts: z.array(Part),
-      metadata: z.object({
-        time: z.object({
-          created: z.number(),
-          completed: z.number().optional(),
-        }),
-        error: z
-          .discriminatedUnion("name", [
-            Provider.AuthError.Schema,
-            NamedError.Unknown.Schema,
-          ])
-          .optional(),
-        sessionID: z.string(),
-        tool: z.record(
-          z.string(),
-          z
+      metadata: z
+        .object({
+          time: z.object({
+            created: z.number(),
+            completed: z.number().optional(),
+          }),
+          error: z
+            .discriminatedUnion("name", [
+              Provider.AuthError.Schema,
+              NamedError.Unknown.Schema,
+            ])
+            .optional(),
+          sessionID: z.string(),
+          tool: z.record(
+            z.string(),
+            z
+              .object({
+                title: z.string(),
+                time: z.object({
+                  start: z.number(),
+                  end: z.number(),
+                }),
+              })
+              .catchall(z.any()),
+          ),
+          assistant: z
             .object({
-              title: z.string(),
-              time: z.object({
-                start: z.number(),
-                end: z.number(),
+              system: z.string().array(),
+              modelID: z.string(),
+              providerID: z.string(),
+              path: z.object({
+                cwd: z.string(),
+                root: z.string(),
               }),
-            })
-            .catchall(z.any()),
-        ),
-        assistant: z
-          .object({
-            system: z.string().array(),
-            modelID: z.string(),
-            providerID: z.string(),
-            path: z.object({
-              cwd: z.string(),
-              root: z.string(),
-            }),
-            cost: z.number(),
-            summary: z.boolean().optional(),
-            tokens: z.object({
-              input: z.number(),
-              output: z.number(),
-              reasoning: z.number(),
-              cache: z.object({
-                read: z.number(),
-                write: z.number(),
+              cost: z.number(),
+              summary: z.boolean().optional(),
+              tokens: z.object({
+                input: z.number(),
+                output: z.number(),
+                reasoning: z.number(),
+                cache: z.object({
+                  read: z.number(),
+                  write: z.number(),
+                }),
               }),
-            }),
-          })
-          .optional(),
-      }),
+            })
+            .optional(),
+        })
+        .openapi({ ref: "Message.Metadata" }),
     })
     .openapi({
       ref: "Message.Info",

+ 34 - 14
packages/tui/internal/app/app.go

@@ -6,11 +6,13 @@ import (
 	"path/filepath"
 	"sort"
 	"strings"
+	"time"
 
 	"log/slog"
 
 	tea "github.com/charmbracelet/bubbletea/v2"
 	"github.com/sst/opencode/internal/commands"
+	"github.com/sst/opencode/internal/components/toast"
 	"github.com/sst/opencode/internal/config"
 	"github.com/sst/opencode/internal/theme"
 	"github.com/sst/opencode/internal/util"
@@ -47,6 +49,9 @@ type SendMsg struct {
 type CompletionDialogTriggeredMsg struct {
 	InitialValue string
 }
+type OptimisticMessageAddedMsg struct {
+	Message client.MessageInfo
+}
 
 func New(
 	ctx context.Context,
@@ -297,19 +302,12 @@ func (a *App) SendChatMessage(ctx context.Context, text string, attachments []At
 	if a.Session.Id == "" {
 		session, err := a.CreateSession(ctx)
 		if err != nil {
-			// status.Error(err.Error())
-			return nil
+			return toast.NewErrorToast(err.Error())
 		}
 		a.Session = session
 		cmds = append(cmds, util.CmdHandler(SessionSelectedMsg(session)))
 	}
 
-	// TODO: Handle attachments when API supports them
-	if len(attachments) > 0 {
-		// For now, ignore attachments
-		// return "", fmt.Errorf("attachments not supported yet")
-	}
-
 	part := client.MessagePart{}
 	part.FromMessagePartText(client.MessagePartText{
 		Type: "text",
@@ -317,7 +315,26 @@ func (a *App) SendChatMessage(ctx context.Context, text string, attachments []At
 	})
 	parts := []client.MessagePart{part}
 
-	go func() {
+	optimisticMessage := client.MessageInfo{
+		Id:    fmt.Sprintf("optimistic-%d", time.Now().UnixNano()),
+		Role:  client.User,
+		Parts: parts,
+		Metadata: client.MessageMetadata{
+			SessionID: a.Session.Id,
+			Time: struct {
+				Completed *float32 `json:"completed,omitempty"`
+				Created   float32  `json:"created"`
+			}{
+				Created: float32(time.Now().Unix()),
+			},
+			Tool: make(map[string]client.MessageMetadata_Tool_AdditionalProperties),
+		},
+	}
+
+	a.Messages = append(a.Messages, optimisticMessage)
+	cmds = append(cmds, util.CmdHandler(OptimisticMessageAddedMsg{Message: optimisticMessage}))
+
+	cmds = append(cmds, func() tea.Msg {
 		response, err := a.Client.PostSessionChat(ctx, client.PostSessionChatJSONRequestBody{
 			SessionID:  a.Session.Id,
 			Parts:      parts,
@@ -325,14 +342,17 @@ func (a *App) SendChatMessage(ctx context.Context, text string, attachments []At
 			ModelID:    a.Model.Id,
 		})
 		if err != nil {
-			slog.Error("Failed to send message", "error", err)
-			// status.Error(err.Error())
+			errormsg := fmt.Sprintf("failed to send message: %v", err)
+			slog.Error(errormsg)
+			return toast.NewErrorToast(errormsg)()
 		}
 		if response != nil && response.StatusCode != 200 {
-			slog.Error("Failed to send message", "error", fmt.Sprintf("failed to send message: %d", response.StatusCode))
-			// status.Error(fmt.Sprintf("failed to send message: %d", response.StatusCode))
+			errormsg := fmt.Sprintf("failed to send message: %d", response.StatusCode)
+			slog.Error(errormsg)
+			return toast.NewErrorToast(errormsg)()
 		}
-	}()
+		return nil
+	})
 
 	// The actual response will come through SSE
 	// For now, just return success

+ 2 - 2
packages/tui/internal/components/chat/message.go

@@ -253,7 +253,7 @@ func renderText(message client.MessageInfo, text string, author string) string {
 func renderToolInvocation(
 	toolCall client.MessageToolInvocationToolCall,
 	result *string,
-	metadata client.MessageInfo_Metadata_Tool_AdditionalProperties,
+	metadata client.MessageMetadata_Tool_AdditionalProperties,
 	showDetails bool,
 	isLast bool,
 	contentOnly bool,
@@ -466,7 +466,7 @@ func renderToolInvocation(
 
 						if metadata, ok := call["metadata"].(map[string]any); ok {
 							data, _ = json.Marshal(metadata)
-							var toolMetadata client.MessageInfo_Metadata_Tool_AdditionalProperties
+							var toolMetadata client.MessageMetadata_Tool_AdditionalProperties
 							_ = json.Unmarshal(data, &toolMetadata)
 
 							step := renderToolInvocation(

+ 7 - 1
packages/tui/internal/components/chat/messages.go

@@ -58,6 +58,12 @@ func (m *messagesComponent) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
 		m.viewport.GotoBottom()
 		m.tail = true
 		return m, nil
+	case app.OptimisticMessageAddedMsg:
+		m.renderView()
+		if m.tail {
+			m.viewport.GotoBottom()
+		}
+		return m, nil
 	case dialog.ThemeSelectedMsg:
 		m.cache.Clear()
 		return m, m.Reload()
@@ -171,7 +177,7 @@ func (m *messagesComponent) renderView() {
 				isLastToolInvocation := slices.Contains(lastToolIndices, i)
 				toolInvocationPart := part.(client.MessagePartToolInvocation)
 				toolCall, _ := toolInvocationPart.ToolInvocation.AsMessageToolInvocationToolCall()
-				metadata := client.MessageInfo_Metadata_Tool_AdditionalProperties{}
+				metadata := client.MessageMetadata_Tool_AdditionalProperties{}
 				if _, ok := message.Metadata.Tool[toolCall.ToolCallId]; ok {
 					metadata = message.Metadata.Tool[toolCall.ToolCallId]
 				}

+ 25 - 4
packages/tui/internal/tui/tui.go

@@ -230,12 +230,33 @@ func (a appModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
 	case client.EventMessageUpdated:
 		if msg.Properties.Info.Metadata.SessionID == a.app.Session.Id {
 			exists := false
-			for i, m := range a.app.Messages {
-				if m.Id == msg.Properties.Info.Id {
-					a.app.Messages[i] = msg.Properties.Info
-					exists = true
+			optimisticReplaced := false
+			
+			// First check if this is replacing an optimistic message
+			if msg.Properties.Info.Role == client.User {
+				// Look for optimistic messages to replace
+				for i, m := range a.app.Messages {
+					if strings.HasPrefix(m.Id, "optimistic-") && m.Role == client.User {
+						// Replace the optimistic message with the real one
+						a.app.Messages[i] = msg.Properties.Info
+						exists = true
+						optimisticReplaced = true
+						break
+					}
 				}
 			}
+			
+			// 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
+						exists = true
+						break
+					}
+				}
+			}
+			
 			if !exists {
 				a.app.Messages = append(a.app.Messages, msg.Properties.Info)
 			}

+ 218 - 159
packages/tui/pkg/client/gen/openapi.json

@@ -230,6 +230,42 @@
         }
       }
     },
+    "/session_unshare": {
+      "post": {
+        "responses": {
+          "200": {
+            "description": "Successfully unshared session",
+            "content": {
+              "application/json": {
+                "schema": {
+                  "$ref": "#/components/schemas/session.info"
+                }
+              }
+            }
+          }
+        },
+        "operationId": "postSession_unshare",
+        "parameters": [],
+        "description": "Unshare the session",
+        "requestBody": {
+          "content": {
+            "application/json": {
+              "schema": {
+                "type": "object",
+                "properties": {
+                  "sessionID": {
+                    "type": "string"
+                  }
+                },
+                "required": [
+                  "sessionID"
+                ]
+              }
+            }
+          }
+        }
+      }
+    },
     "/session_messages": {
       "post": {
         "responses": {
@@ -734,160 +770,7 @@
             }
           },
           "metadata": {
-            "type": "object",
-            "properties": {
-              "time": {
-                "type": "object",
-                "properties": {
-                  "created": {
-                    "type": "number"
-                  },
-                  "completed": {
-                    "type": "number"
-                  }
-                },
-                "required": [
-                  "created"
-                ]
-              },
-              "error": {
-                "oneOf": [
-                  {
-                    "$ref": "#/components/schemas/ProviderAuthError"
-                  },
-                  {
-                    "$ref": "#/components/schemas/UnknownError"
-                  }
-                ],
-                "discriminator": {
-                  "propertyName": "name",
-                  "mapping": {
-                    "ProviderAuthError": "#/components/schemas/ProviderAuthError",
-                    "UnknownError": "#/components/schemas/UnknownError"
-                  }
-                }
-              },
-              "sessionID": {
-                "type": "string"
-              },
-              "tool": {
-                "type": "object",
-                "additionalProperties": {
-                  "type": "object",
-                  "properties": {
-                    "title": {
-                      "type": "string"
-                    },
-                    "time": {
-                      "type": "object",
-                      "properties": {
-                        "start": {
-                          "type": "number"
-                        },
-                        "end": {
-                          "type": "number"
-                        }
-                      },
-                      "required": [
-                        "start",
-                        "end"
-                      ]
-                    }
-                  },
-                  "required": [
-                    "title",
-                    "time"
-                  ],
-                  "additionalProperties": {}
-                }
-              },
-              "assistant": {
-                "type": "object",
-                "properties": {
-                  "system": {
-                    "type": "array",
-                    "items": {
-                      "type": "string"
-                    }
-                  },
-                  "modelID": {
-                    "type": "string"
-                  },
-                  "providerID": {
-                    "type": "string"
-                  },
-                  "path": {
-                    "type": "object",
-                    "properties": {
-                      "cwd": {
-                        "type": "string"
-                      },
-                      "root": {
-                        "type": "string"
-                      }
-                    },
-                    "required": [
-                      "cwd",
-                      "root"
-                    ]
-                  },
-                  "cost": {
-                    "type": "number"
-                  },
-                  "summary": {
-                    "type": "boolean"
-                  },
-                  "tokens": {
-                    "type": "object",
-                    "properties": {
-                      "input": {
-                        "type": "number"
-                      },
-                      "output": {
-                        "type": "number"
-                      },
-                      "reasoning": {
-                        "type": "number"
-                      },
-                      "cache": {
-                        "type": "object",
-                        "properties": {
-                          "read": {
-                            "type": "number"
-                          },
-                          "write": {
-                            "type": "number"
-                          }
-                        },
-                        "required": [
-                          "read",
-                          "write"
-                        ]
-                      }
-                    },
-                    "required": [
-                      "input",
-                      "output",
-                      "reasoning",
-                      "cache"
-                    ]
-                  }
-                },
-                "required": [
-                  "system",
-                  "modelID",
-                  "providerID",
-                  "path",
-                  "cost",
-                  "tokens"
-                ]
-              }
-            },
-            "required": [
-              "time",
-              "sessionID",
-              "tool"
-            ]
+            "$ref": "#/components/schemas/Message.Metadata"
           }
         },
         "required": [
@@ -1141,6 +1024,162 @@
           "type"
         ]
       },
+      "Message.Metadata": {
+        "type": "object",
+        "properties": {
+          "time": {
+            "type": "object",
+            "properties": {
+              "created": {
+                "type": "number"
+              },
+              "completed": {
+                "type": "number"
+              }
+            },
+            "required": [
+              "created"
+            ]
+          },
+          "error": {
+            "oneOf": [
+              {
+                "$ref": "#/components/schemas/ProviderAuthError"
+              },
+              {
+                "$ref": "#/components/schemas/UnknownError"
+              }
+            ],
+            "discriminator": {
+              "propertyName": "name",
+              "mapping": {
+                "ProviderAuthError": "#/components/schemas/ProviderAuthError",
+                "UnknownError": "#/components/schemas/UnknownError"
+              }
+            }
+          },
+          "sessionID": {
+            "type": "string"
+          },
+          "tool": {
+            "type": "object",
+            "additionalProperties": {
+              "type": "object",
+              "properties": {
+                "title": {
+                  "type": "string"
+                },
+                "time": {
+                  "type": "object",
+                  "properties": {
+                    "start": {
+                      "type": "number"
+                    },
+                    "end": {
+                      "type": "number"
+                    }
+                  },
+                  "required": [
+                    "start",
+                    "end"
+                  ]
+                }
+              },
+              "required": [
+                "title",
+                "time"
+              ],
+              "additionalProperties": {}
+            }
+          },
+          "assistant": {
+            "type": "object",
+            "properties": {
+              "system": {
+                "type": "array",
+                "items": {
+                  "type": "string"
+                }
+              },
+              "modelID": {
+                "type": "string"
+              },
+              "providerID": {
+                "type": "string"
+              },
+              "path": {
+                "type": "object",
+                "properties": {
+                  "cwd": {
+                    "type": "string"
+                  },
+                  "root": {
+                    "type": "string"
+                  }
+                },
+                "required": [
+                  "cwd",
+                  "root"
+                ]
+              },
+              "cost": {
+                "type": "number"
+              },
+              "summary": {
+                "type": "boolean"
+              },
+              "tokens": {
+                "type": "object",
+                "properties": {
+                  "input": {
+                    "type": "number"
+                  },
+                  "output": {
+                    "type": "number"
+                  },
+                  "reasoning": {
+                    "type": "number"
+                  },
+                  "cache": {
+                    "type": "object",
+                    "properties": {
+                      "read": {
+                        "type": "number"
+                      },
+                      "write": {
+                        "type": "number"
+                      }
+                    },
+                    "required": [
+                      "read",
+                      "write"
+                    ]
+                  }
+                },
+                "required": [
+                  "input",
+                  "output",
+                  "reasoning",
+                  "cache"
+                ]
+              }
+            },
+            "required": [
+              "system",
+              "modelID",
+              "providerID",
+              "path",
+              "cost",
+              "tokens"
+            ]
+          }
+        },
+        "required": [
+          "time",
+          "sessionID",
+          "tool"
+        ]
+      },
       "ProviderAuthError": {
         "type": "object",
         "properties": {
@@ -1461,6 +1500,9 @@
                       "temperature": {
                         "type": "boolean"
                       },
+                      "tool_call": {
+                        "type": "boolean"
+                      },
                       "cost": {
                         "type": "object",
                         "properties": {
@@ -1499,6 +1541,10 @@
                       },
                       "id": {
                         "type": "string"
+                      },
+                      "options": {
+                        "type": "object",
+                        "additionalProperties": {}
                       }
                     }
                   }
@@ -1535,7 +1581,8 @@
             },
             "description": "MCP (Model Context Protocol) server configurations"
           }
-        }
+        },
+        "additionalProperties": false
       },
       "Config.Keybinds": {
         "type": "object",
@@ -1648,7 +1695,8 @@
             "type": "string",
             "description": "Exit the application"
           }
-        }
+        },
+        "additionalProperties": false
       },
       "Provider.Info": {
         "type": "object",
@@ -1700,6 +1748,9 @@
           "temperature": {
             "type": "boolean"
           },
+          "tool_call": {
+            "type": "boolean"
+          },
           "cost": {
             "type": "object",
             "properties": {
@@ -1738,6 +1789,10 @@
           },
           "id": {
             "type": "string"
+          },
+          "options": {
+            "type": "object",
+            "additionalProperties": {}
           }
         },
         "required": [
@@ -1745,9 +1800,11 @@
           "attachment",
           "reasoning",
           "temperature",
+          "tool_call",
           "cost",
           "limit",
-          "id"
+          "id",
+          "options"
         ]
       },
       "Config.McpLocal": {
@@ -1776,7 +1833,8 @@
         "required": [
           "type",
           "command"
-        ]
+        ],
+        "additionalProperties": false
       },
       "Config.McpRemote": {
         "type": "object",
@@ -1794,7 +1852,8 @@
         "required": [
           "type",
           "url"
-        ]
+        ],
+        "additionalProperties": false
       },
       "Error": {
         "type": "object",

+ 226 - 72
packages/tui/pkg/client/generated-client.go

@@ -78,9 +78,11 @@ type ConfigInfo struct {
 				Context float32 `json:"context"`
 				Output  float32 `json:"output"`
 			} `json:"limit,omitempty"`
-			Name        *string `json:"name,omitempty"`
-			Reasoning   *bool   `json:"reasoning,omitempty"`
-			Temperature *bool   `json:"temperature,omitempty"`
+			Name        *string                 `json:"name,omitempty"`
+			Options     *map[string]interface{} `json:"options,omitempty"`
+			Reasoning   *bool                   `json:"reasoning,omitempty"`
+			Temperature *bool                   `json:"temperature,omitempty"`
+			ToolCall    *bool                   `json:"tool_call,omitempty"`
 		} `json:"models"`
 		Name    *string                 `json:"name,omitempty"`
 		Npm     *string                 `json:"npm,omitempty"`
@@ -290,47 +292,53 @@ type InstallationInfo struct {
 
 // MessageInfo defines model for Message.Info.
 type MessageInfo struct {
-	Id       string `json:"id"`
-	Metadata struct {
-		Assistant *struct {
-			Cost    float32 `json:"cost"`
-			ModelID string  `json:"modelID"`
-			Path    struct {
-				Cwd  string `json:"cwd"`
-				Root string `json:"root"`
-			} `json:"path"`
-			ProviderID string   `json:"providerID"`
-			Summary    *bool    `json:"summary,omitempty"`
-			System     []string `json:"system"`
-			Tokens     struct {
-				Cache struct {
-					Read  float32 `json:"read"`
-					Write float32 `json:"write"`
-				} `json:"cache"`
-				Input     float32 `json:"input"`
-				Output    float32 `json:"output"`
-				Reasoning float32 `json:"reasoning"`
-			} `json:"tokens"`
-		} `json:"assistant,omitempty"`
-		Error     *MessageInfo_Metadata_Error `json:"error,omitempty"`
-		SessionID string                      `json:"sessionID"`
-		Time      struct {
-			Completed *float32 `json:"completed,omitempty"`
-			Created   float32  `json:"created"`
-		} `json:"time"`
-		Tool map[string]MessageInfo_Metadata_Tool_AdditionalProperties `json:"tool"`
-	} `json:"metadata"`
-	Parts []MessagePart   `json:"parts"`
-	Role  MessageInfoRole `json:"role"`
-}
-
-// MessageInfo_Metadata_Error defines model for MessageInfo.Metadata.Error.
-type MessageInfo_Metadata_Error struct {
+	Id       string          `json:"id"`
+	Metadata MessageMetadata `json:"metadata"`
+	Parts    []MessagePart   `json:"parts"`
+	Role     MessageInfoRole `json:"role"`
+}
+
+// MessageInfoRole defines model for MessageInfo.Role.
+type MessageInfoRole string
+
+// MessageMetadata defines model for Message.Metadata.
+type MessageMetadata struct {
+	Assistant *struct {
+		Cost    float32 `json:"cost"`
+		ModelID string  `json:"modelID"`
+		Path    struct {
+			Cwd  string `json:"cwd"`
+			Root string `json:"root"`
+		} `json:"path"`
+		ProviderID string   `json:"providerID"`
+		Summary    *bool    `json:"summary,omitempty"`
+		System     []string `json:"system"`
+		Tokens     struct {
+			Cache struct {
+				Read  float32 `json:"read"`
+				Write float32 `json:"write"`
+			} `json:"cache"`
+			Input     float32 `json:"input"`
+			Output    float32 `json:"output"`
+			Reasoning float32 `json:"reasoning"`
+		} `json:"tokens"`
+	} `json:"assistant,omitempty"`
+	Error     *MessageMetadata_Error `json:"error,omitempty"`
+	SessionID string                 `json:"sessionID"`
+	Time      struct {
+		Completed *float32 `json:"completed,omitempty"`
+		Created   float32  `json:"created"`
+	} `json:"time"`
+	Tool map[string]MessageMetadata_Tool_AdditionalProperties `json:"tool"`
+}
+
+// MessageMetadata_Error defines model for MessageMetadata.Error.
+type MessageMetadata_Error struct {
 	union json.RawMessage
 }
 
-// MessageInfo_Metadata_Tool_AdditionalProperties defines model for MessageInfo.Metadata.Tool.AdditionalProperties.
-type MessageInfo_Metadata_Tool_AdditionalProperties struct {
+// MessageMetadata_Tool_AdditionalProperties defines model for Message.Metadata.tool.AdditionalProperties.
+type MessageMetadata_Tool_AdditionalProperties struct {
 	Time struct {
 		End   float32 `json:"end"`
 		Start float32 `json:"start"`
@@ -339,9 +347,6 @@ type MessageInfo_Metadata_Tool_AdditionalProperties struct {
 	AdditionalProperties map[string]interface{} `json:"-"`
 }
 
-// MessageInfoRole defines model for MessageInfo.Role.
-type MessageInfoRole string
-
 // MessagePart defines model for Message.Part.
 type MessagePart struct {
 	union json.RawMessage
@@ -435,9 +440,11 @@ type ModelInfo struct {
 		Context float32 `json:"context"`
 		Output  float32 `json:"output"`
 	} `json:"limit"`
-	Name        string `json:"name"`
-	Reasoning   bool   `json:"reasoning"`
-	Temperature bool   `json:"temperature"`
+	Name        string                 `json:"name"`
+	Options     map[string]interface{} `json:"options"`
+	Reasoning   bool                   `json:"reasoning"`
+	Temperature bool                   `json:"temperature"`
+	ToolCall    bool                   `json:"tool_call"`
 }
 
 // ProviderInfo defines model for Provider.Info.
@@ -535,6 +542,11 @@ type PostSessionSummarizeJSONBody struct {
 	SessionID  string `json:"sessionID"`
 }
 
+// PostSessionUnshareJSONBody defines parameters for PostSessionUnshare.
+type PostSessionUnshareJSONBody struct {
+	SessionID string `json:"sessionID"`
+}
+
 // PostFileSearchJSONRequestBody defines body for PostFileSearch for application/json ContentType.
 type PostFileSearchJSONRequestBody PostFileSearchJSONBody
 
@@ -556,25 +568,28 @@ type PostSessionShareJSONRequestBody PostSessionShareJSONBody
 // PostSessionSummarizeJSONRequestBody defines body for PostSessionSummarize for application/json ContentType.
 type PostSessionSummarizeJSONRequestBody PostSessionSummarizeJSONBody
 
-// Getter for additional properties for MessageInfo_Metadata_Tool_AdditionalProperties. Returns the specified
+// PostSessionUnshareJSONRequestBody defines body for PostSessionUnshare for application/json ContentType.
+type PostSessionUnshareJSONRequestBody PostSessionUnshareJSONBody
+
+// Getter for additional properties for MessageMetadata_Tool_AdditionalProperties. Returns the specified
 // element and whether it was found
-func (a MessageInfo_Metadata_Tool_AdditionalProperties) Get(fieldName string) (value interface{}, found bool) {
+func (a MessageMetadata_Tool_AdditionalProperties) Get(fieldName string) (value interface{}, found bool) {
 	if a.AdditionalProperties != nil {
 		value, found = a.AdditionalProperties[fieldName]
 	}
 	return
 }
 
-// Setter for additional properties for MessageInfo_Metadata_Tool_AdditionalProperties
-func (a *MessageInfo_Metadata_Tool_AdditionalProperties) Set(fieldName string, value interface{}) {
+// Setter for additional properties for MessageMetadata_Tool_AdditionalProperties
+func (a *MessageMetadata_Tool_AdditionalProperties) Set(fieldName string, value interface{}) {
 	if a.AdditionalProperties == nil {
 		a.AdditionalProperties = make(map[string]interface{})
 	}
 	a.AdditionalProperties[fieldName] = value
 }
 
-// Override default JSON handling for MessageInfo_Metadata_Tool_AdditionalProperties to handle AdditionalProperties
-func (a *MessageInfo_Metadata_Tool_AdditionalProperties) UnmarshalJSON(b []byte) error {
+// Override default JSON handling for MessageMetadata_Tool_AdditionalProperties to handle AdditionalProperties
+func (a *MessageMetadata_Tool_AdditionalProperties) UnmarshalJSON(b []byte) error {
 	object := make(map[string]json.RawMessage)
 	err := json.Unmarshal(b, &object)
 	if err != nil {
@@ -603,7 +618,7 @@ func (a *MessageInfo_Metadata_Tool_AdditionalProperties) UnmarshalJSON(b []byte)
 			var fieldVal interface{}
 			err := json.Unmarshal(fieldBuf, &fieldVal)
 			if err != nil {
-				return fmt.Errorf("error unmarshalling field %s: %w", fieldName, err)
+				return fmt.Errorf("error unmarshaling field %s: %w", fieldName, err)
 			}
 			a.AdditionalProperties[fieldName] = fieldVal
 		}
@@ -611,8 +626,8 @@ func (a *MessageInfo_Metadata_Tool_AdditionalProperties) UnmarshalJSON(b []byte)
 	return nil
 }
 
-// Override default JSON handling for MessageInfo_Metadata_Tool_AdditionalProperties to handle AdditionalProperties
-func (a MessageInfo_Metadata_Tool_AdditionalProperties) MarshalJSON() ([]byte, error) {
+// Override default JSON handling for MessageMetadata_Tool_AdditionalProperties to handle AdditionalProperties
+func (a MessageMetadata_Tool_AdditionalProperties) MarshalJSON() ([]byte, error) {
 	var err error
 	object := make(map[string]json.RawMessage)
 
@@ -1082,23 +1097,23 @@ func (t *EventSessionError_Properties_Error) UnmarshalJSON(b []byte) error {
 	return err
 }
 
-// AsProviderAuthError returns the union data inside the MessageInfo_Metadata_Error as a ProviderAuthError
-func (t MessageInfo_Metadata_Error) AsProviderAuthError() (ProviderAuthError, error) {
+// AsProviderAuthError returns the union data inside the MessageMetadata_Error as a ProviderAuthError
+func (t MessageMetadata_Error) AsProviderAuthError() (ProviderAuthError, error) {
 	var body ProviderAuthError
 	err := json.Unmarshal(t.union, &body)
 	return body, err
 }
 
-// FromProviderAuthError overwrites any union data inside the MessageInfo_Metadata_Error as the provided ProviderAuthError
-func (t *MessageInfo_Metadata_Error) FromProviderAuthError(v ProviderAuthError) error {
+// FromProviderAuthError overwrites any union data inside the MessageMetadata_Error as the provided ProviderAuthError
+func (t *MessageMetadata_Error) FromProviderAuthError(v ProviderAuthError) error {
 	v.Name = "ProviderAuthError"
 	b, err := json.Marshal(v)
 	t.union = b
 	return err
 }
 
-// MergeProviderAuthError performs a merge with any union data inside the MessageInfo_Metadata_Error, using the provided ProviderAuthError
-func (t *MessageInfo_Metadata_Error) MergeProviderAuthError(v ProviderAuthError) error {
+// MergeProviderAuthError performs a merge with any union data inside the MessageMetadata_Error, using the provided ProviderAuthError
+func (t *MessageMetadata_Error) MergeProviderAuthError(v ProviderAuthError) error {
 	v.Name = "ProviderAuthError"
 	b, err := json.Marshal(v)
 	if err != nil {
@@ -1110,23 +1125,23 @@ func (t *MessageInfo_Metadata_Error) MergeProviderAuthError(v ProviderAuthError)
 	return err
 }
 
-// AsUnknownError returns the union data inside the MessageInfo_Metadata_Error as a UnknownError
-func (t MessageInfo_Metadata_Error) AsUnknownError() (UnknownError, error) {
+// AsUnknownError returns the union data inside the MessageMetadata_Error as a UnknownError
+func (t MessageMetadata_Error) AsUnknownError() (UnknownError, error) {
 	var body UnknownError
 	err := json.Unmarshal(t.union, &body)
 	return body, err
 }
 
-// FromUnknownError overwrites any union data inside the MessageInfo_Metadata_Error as the provided UnknownError
-func (t *MessageInfo_Metadata_Error) FromUnknownError(v UnknownError) error {
+// FromUnknownError overwrites any union data inside the MessageMetadata_Error as the provided UnknownError
+func (t *MessageMetadata_Error) FromUnknownError(v UnknownError) error {
 	v.Name = "UnknownError"
 	b, err := json.Marshal(v)
 	t.union = b
 	return err
 }
 
-// MergeUnknownError performs a merge with any union data inside the MessageInfo_Metadata_Error, using the provided UnknownError
-func (t *MessageInfo_Metadata_Error) MergeUnknownError(v UnknownError) error {
+// MergeUnknownError performs a merge with any union data inside the MessageMetadata_Error, using the provided UnknownError
+func (t *MessageMetadata_Error) MergeUnknownError(v UnknownError) error {
 	v.Name = "UnknownError"
 	b, err := json.Marshal(v)
 	if err != nil {
@@ -1138,7 +1153,7 @@ func (t *MessageInfo_Metadata_Error) MergeUnknownError(v UnknownError) error {
 	return err
 }
 
-func (t MessageInfo_Metadata_Error) Discriminator() (string, error) {
+func (t MessageMetadata_Error) Discriminator() (string, error) {
 	var discriminator struct {
 		Discriminator string `json:"name"`
 	}
@@ -1146,7 +1161,7 @@ func (t MessageInfo_Metadata_Error) Discriminator() (string, error) {
 	return discriminator.Discriminator, err
 }
 
-func (t MessageInfo_Metadata_Error) ValueByDiscriminator() (interface{}, error) {
+func (t MessageMetadata_Error) ValueByDiscriminator() (interface{}, error) {
 	discriminator, err := t.Discriminator()
 	if err != nil {
 		return nil, err
@@ -1161,12 +1176,12 @@ func (t MessageInfo_Metadata_Error) ValueByDiscriminator() (interface{}, error)
 	}
 }
 
-func (t MessageInfo_Metadata_Error) MarshalJSON() ([]byte, error) {
+func (t MessageMetadata_Error) MarshalJSON() ([]byte, error) {
 	b, err := t.union.MarshalJSON()
 	return b, err
 }
 
-func (t *MessageInfo_Metadata_Error) UnmarshalJSON(b []byte) error {
+func (t *MessageMetadata_Error) UnmarshalJSON(b []byte) error {
 	err := t.union.UnmarshalJSON(b)
 	return err
 }
@@ -1633,6 +1648,11 @@ type ClientInterface interface {
 	PostSessionSummarizeWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error)
 
 	PostSessionSummarize(ctx context.Context, body PostSessionSummarizeJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error)
+
+	// PostSessionUnshareWithBody request with any body
+	PostSessionUnshareWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error)
+
+	PostSessionUnshare(ctx context.Context, body PostSessionUnshareJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error)
 }
 
 func (c *Client) PostAppInfo(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) {
@@ -1911,6 +1931,30 @@ func (c *Client) PostSessionSummarize(ctx context.Context, body PostSessionSumma
 	return c.Client.Do(req)
 }
 
+func (c *Client) PostSessionUnshareWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) {
+	req, err := NewPostSessionUnshareRequestWithBody(c.Server, contentType, body)
+	if err != nil {
+		return nil, err
+	}
+	req = req.WithContext(ctx)
+	if err := c.applyEditors(ctx, req, reqEditors); err != nil {
+		return nil, err
+	}
+	return c.Client.Do(req)
+}
+
+func (c *Client) PostSessionUnshare(ctx context.Context, body PostSessionUnshareJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) {
+	req, err := NewPostSessionUnshareRequest(c.Server, body)
+	if err != nil {
+		return nil, err
+	}
+	req = req.WithContext(ctx)
+	if err := c.applyEditors(ctx, req, reqEditors); err != nil {
+		return nil, err
+	}
+	return c.Client.Do(req)
+}
+
 // NewPostAppInfoRequest generates requests for PostAppInfo
 func NewPostAppInfoRequest(server string) (*http.Request, error) {
 	var err error
@@ -2434,6 +2478,46 @@ func NewPostSessionSummarizeRequestWithBody(server string, contentType string, b
 	return req, nil
 }
 
+// NewPostSessionUnshareRequest calls the generic PostSessionUnshare builder with application/json body
+func NewPostSessionUnshareRequest(server string, body PostSessionUnshareJSONRequestBody) (*http.Request, error) {
+	var bodyReader io.Reader
+	buf, err := json.Marshal(body)
+	if err != nil {
+		return nil, err
+	}
+	bodyReader = bytes.NewReader(buf)
+	return NewPostSessionUnshareRequestWithBody(server, "application/json", bodyReader)
+}
+
+// NewPostSessionUnshareRequestWithBody generates requests for PostSessionUnshare with any type of body
+func NewPostSessionUnshareRequestWithBody(server string, contentType string, body io.Reader) (*http.Request, error) {
+	var err error
+
+	serverURL, err := url.Parse(server)
+	if err != nil {
+		return nil, err
+	}
+
+	operationPath := fmt.Sprintf("/session_unshare")
+	if operationPath[0] == '/' {
+		operationPath = "." + operationPath
+	}
+
+	queryURL, err := serverURL.Parse(operationPath)
+	if err != nil {
+		return nil, err
+	}
+
+	req, err := http.NewRequest("POST", queryURL.String(), body)
+	if err != nil {
+		return nil, err
+	}
+
+	req.Header.Add("Content-Type", contentType)
+
+	return req, nil
+}
+
 func (c *Client) applyEditors(ctx context.Context, req *http.Request, additionalEditors []RequestEditorFn) error {
 	for _, r := range c.RequestEditors {
 		if err := r(ctx, req); err != nil {
@@ -2538,6 +2622,11 @@ type ClientWithResponsesInterface interface {
 	PostSessionSummarizeWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostSessionSummarizeResponse, error)
 
 	PostSessionSummarizeWithResponse(ctx context.Context, body PostSessionSummarizeJSONRequestBody, reqEditors ...RequestEditorFn) (*PostSessionSummarizeResponse, error)
+
+	// PostSessionUnshareWithBodyWithResponse request with any body
+	PostSessionUnshareWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostSessionUnshareResponse, error)
+
+	PostSessionUnshareWithResponse(ctx context.Context, body PostSessionUnshareJSONRequestBody, reqEditors ...RequestEditorFn) (*PostSessionUnshareResponse, error)
 }
 
 type PostAppInfoResponse struct {
@@ -2901,6 +2990,28 @@ func (r PostSessionSummarizeResponse) StatusCode() int {
 	return 0
 }
 
+type PostSessionUnshareResponse struct {
+	Body         []byte
+	HTTPResponse *http.Response
+	JSON200      *SessionInfo
+}
+
+// Status returns HTTPResponse.Status
+func (r PostSessionUnshareResponse) Status() string {
+	if r.HTTPResponse != nil {
+		return r.HTTPResponse.Status
+	}
+	return http.StatusText(0)
+}
+
+// StatusCode returns HTTPResponse.StatusCode
+func (r PostSessionUnshareResponse) StatusCode() int {
+	if r.HTTPResponse != nil {
+		return r.HTTPResponse.StatusCode
+	}
+	return 0
+}
+
 // PostAppInfoWithResponse request returning *PostAppInfoResponse
 func (c *ClientWithResponses) PostAppInfoWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*PostAppInfoResponse, error) {
 	rsp, err := c.PostAppInfo(ctx, reqEditors...)
@@ -3101,6 +3212,23 @@ func (c *ClientWithResponses) PostSessionSummarizeWithResponse(ctx context.Conte
 	return ParsePostSessionSummarizeResponse(rsp)
 }
 
+// PostSessionUnshareWithBodyWithResponse request with arbitrary body returning *PostSessionUnshareResponse
+func (c *ClientWithResponses) PostSessionUnshareWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostSessionUnshareResponse, error) {
+	rsp, err := c.PostSessionUnshareWithBody(ctx, contentType, body, reqEditors...)
+	if err != nil {
+		return nil, err
+	}
+	return ParsePostSessionUnshareResponse(rsp)
+}
+
+func (c *ClientWithResponses) PostSessionUnshareWithResponse(ctx context.Context, body PostSessionUnshareJSONRequestBody, reqEditors ...RequestEditorFn) (*PostSessionUnshareResponse, error) {
+	rsp, err := c.PostSessionUnshare(ctx, body, reqEditors...)
+	if err != nil {
+		return nil, err
+	}
+	return ParsePostSessionUnshareResponse(rsp)
+}
+
 // ParsePostAppInfoResponse parses an HTTP response from a PostAppInfoWithResponse call
 func ParsePostAppInfoResponse(rsp *http.Response) (*PostAppInfoResponse, error) {
 	bodyBytes, err := io.ReadAll(rsp.Body)
@@ -3531,3 +3659,29 @@ func ParsePostSessionSummarizeResponse(rsp *http.Response) (*PostSessionSummariz
 
 	return response, nil
 }
+
+// ParsePostSessionUnshareResponse parses an HTTP response from a PostSessionUnshareWithResponse call
+func ParsePostSessionUnshareResponse(rsp *http.Response) (*PostSessionUnshareResponse, error) {
+	bodyBytes, err := io.ReadAll(rsp.Body)
+	defer func() { _ = rsp.Body.Close() }()
+	if err != nil {
+		return nil, err
+	}
+
+	response := &PostSessionUnshareResponse{
+		Body:         bodyBytes,
+		HTTPResponse: rsp,
+	}
+
+	switch {
+	case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200:
+		var dest SessionInfo
+		if err := json.Unmarshal(bodyBytes, &dest); err != nil {
+			return nil, err
+		}
+		response.JSON200 = &dest
+
+	}
+
+	return response, nil
+}