diff --git a/packages/opencode/src/server/server.ts b/packages/opencode/src/server/server.ts index b096f20f5..173ecbac9 100644 --- a/packages/opencode/src/server/server.ts +++ b/packages/opencode/src/server/server.ts @@ -720,12 +720,7 @@ export namespace Server { }, }, }), - zValidator( - "json", - z.object({ - text: z.string(), - }), - ), + zValidator("json", Session.ChatInput.pick({ parts: true })), async (c) => c.json(await callTui(c)), ) .post( diff --git a/packages/opencode/src/session/index.ts b/packages/opencode/src/session/index.ts index 5f090137a..ac0658758 100644 --- a/packages/opencode/src/session/index.ts +++ b/packages/opencode/src/session/index.ts @@ -330,14 +330,8 @@ export namespace Session { return part } - export const ChatInput = z.object({ - sessionID: Identifier.schema("session"), - messageID: Identifier.schema("message").optional(), - providerID: z.string(), - modelID: z.string(), - mode: z.string().optional(), - tools: z.record(z.boolean()).optional(), - parts: z.array( + export const PartsInput = z + .array( z.discriminatedUnion("type", [ MessageV2.TextPart.omit({ messageID: true, @@ -360,7 +354,19 @@ export namespace Session { ref: "FilePartInput", }), ]), - ), + ) + .openapi({ + ref: "PartsInput", + }) + + export const ChatInput = z.object({ + sessionID: Identifier.schema("session"), + messageID: Identifier.schema("message").optional(), + providerID: z.string(), + modelID: z.string(), + mode: z.string().optional(), + tools: z.record(z.boolean()).optional(), + parts: PartsInput, }) export type ChatInput = z.infer diff --git a/packages/sdk/.stats.yml b/packages/sdk/.stats.yml index f9f86831f..d4064bf8b 100644 --- a/packages/sdk/.stats.yml +++ b/packages/sdk/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 24 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/opencode%2Fopencode-9574184bd9e916aa69eae8e26e0679556038d3fcfb4009a445c97c6cc3e4f3ee.yml -openapi_spec_hash: 93ba1215ab0dc853a1691b049cc47d75 -config_hash: 09e4835d57ec7ed0b2d316c6815bcf0a +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/opencode%2Fopencode-305a02cb514ed54609aa9daae92410230435b7f886f04f790b1db828cd20e524.yml +openapi_spec_hash: b207cc749da156457a2b48c9337aa690 +config_hash: 14ba54419d8428bd5440fd20eba04f99 diff --git a/packages/sdk/api.md b/packages/sdk/api.md index 7cbaaf6c5..ff10ca128 100644 --- a/packages/sdk/api.md +++ b/packages/sdk/api.md @@ -92,6 +92,7 @@ Types: - FileSource - Message - Part +- PartsInput - Session - SnapshotPart - StepFinishPart diff --git a/packages/sdk/src/client.ts b/packages/sdk/src/client.ts index c514ca877..30f2a5443 100644 --- a/packages/sdk/src/client.ts +++ b/packages/sdk/src/client.ts @@ -58,6 +58,7 @@ import { FileSource, Message, Part, + PartsInput, Session, SessionAbortResponse, SessionChatParams, @@ -825,6 +826,7 @@ export declare namespace Opencode { type FileSource as FileSource, type Message as Message, type Part as Part, + type PartsInput as PartsInput, type Session as Session, type SnapshotPart as SnapshotPart, type StepFinishPart as StepFinishPart, diff --git a/packages/sdk/src/resources/config.ts b/packages/sdk/src/resources/config.ts index e1fc09de5..0c8c1c9f4 100644 --- a/packages/sdk/src/resources/config.ts +++ b/packages/sdk/src/resources/config.ts @@ -147,7 +147,7 @@ export namespace Config { npm?: string; - options?: { [key: string]: unknown }; + options?: Provider.Options; } export namespace Provider { @@ -190,6 +190,14 @@ export namespace Config { output: number; } } + + export interface Options { + apiKey?: string; + + baseURL?: string; + + [k: string]: unknown; + } } } diff --git a/packages/sdk/src/resources/index.ts b/packages/sdk/src/resources/index.ts index 50df8ff46..e83acd79d 100644 --- a/packages/sdk/src/resources/index.ts +++ b/packages/sdk/src/resources/index.ts @@ -50,6 +50,7 @@ export { type FileSource, type Message, type Part, + type PartsInput, type Session, type SnapshotPart, type StepFinishPart, diff --git a/packages/sdk/src/resources/session.ts b/packages/sdk/src/resources/session.ts index 6e160321d..0e40cff6b 100644 --- a/packages/sdk/src/resources/session.ts +++ b/packages/sdk/src/resources/session.ts @@ -205,6 +205,8 @@ export type Message = UserMessage | AssistantMessage; export type Part = TextPart | FilePart | ToolPart | StepStartPart | StepFinishPart | SnapshotPart; +export type PartsInput = Array; + export interface Session { id: string; @@ -494,7 +496,7 @@ export type SessionSummarizeResponse = boolean; export interface SessionChatParams { modelID: string; - parts: Array; + parts: PartsInput; providerID: string; @@ -529,6 +531,7 @@ export declare namespace SessionResource { type FileSource as FileSource, type Message as Message, type Part as Part, + type PartsInput as PartsInput, type Session as Session, type SnapshotPart as SnapshotPart, type StepFinishPart as StepFinishPart, diff --git a/packages/sdk/src/resources/tui.ts b/packages/sdk/src/resources/tui.ts index c7efbdd6c..ca82002b8 100644 --- a/packages/sdk/src/resources/tui.ts +++ b/packages/sdk/src/resources/tui.ts @@ -1,6 +1,7 @@ // File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. import { APIResource } from '../core/resource'; +import * as SessionAPI from './session'; import { APIPromise } from '../core/api-promise'; import { RequestOptions } from '../internal/request-options'; @@ -25,7 +26,7 @@ export type TuiAppendPromptResponse = boolean; export type TuiOpenHelpResponse = boolean; export interface TuiAppendPromptParams { - text: string; + parts: SessionAPI.PartsInput; } export declare namespace Tui { diff --git a/packages/sdk/tests/api-resources/tui.test.ts b/packages/sdk/tests/api-resources/tui.test.ts index 8ac0d4359..b8767104b 100644 --- a/packages/sdk/tests/api-resources/tui.test.ts +++ b/packages/sdk/tests/api-resources/tui.test.ts @@ -7,7 +7,7 @@ const client = new Opencode({ baseURL: process.env['TEST_API_BASE_URL'] ?? 'http describe('resource tui', () => { // skipped: tests are disabled for the time being test.skip('appendPrompt: only required params', async () => { - const responsePromise = client.tui.appendPrompt({ text: 'text' }); + const responsePromise = client.tui.appendPrompt({ parts: [{ text: 'text', type: 'text' }] }); const rawResponse = await responsePromise.asResponse(); expect(rawResponse).toBeInstanceOf(Response); const response = await responsePromise; @@ -19,7 +19,9 @@ describe('resource tui', () => { // skipped: tests are disabled for the time being test.skip('appendPrompt: required and optional params', async () => { - const response = await client.tui.appendPrompt({ text: 'text' }); + const response = await client.tui.appendPrompt({ + parts: [{ text: 'text', type: 'text', id: 'id', synthetic: true, time: { start: 0, end: 0 } }], + }); }); // skipped: tests are disabled for the time being diff --git a/packages/tui/internal/app/prompt.go b/packages/tui/internal/app/prompt.go index 9176b7df5..2a7a5058c 100644 --- a/packages/tui/internal/app/prompt.go +++ b/packages/tui/internal/app/prompt.go @@ -1,8 +1,10 @@ package app import ( + "strings" "time" + "github.com/google/uuid" "github.com/sst/opencode-sdk-go" "github.com/sst/opencode/internal/attachment" "github.com/sst/opencode/internal/id" @@ -109,8 +111,8 @@ func (p Prompt) ToMessage( } } -func (m Message) ToSessionChatParams() []opencode.SessionChatParamsPartUnion { - parts := []opencode.SessionChatParamsPartUnion{} +func (m Message) ToSessionChatParams() opencode.PartsInputParam { + parts := []opencode.PartsInputItemUnionParam{} for _, part := range m.Parts { switch p := part.(type) { case opencode.TextPart: @@ -173,8 +175,8 @@ func (m Message) ToSessionChatParams() []opencode.SessionChatParamsPartUnion { return parts } -func (p Prompt) ToSessionChatParams() []opencode.SessionChatParamsPartUnion { - parts := []opencode.SessionChatParamsPartUnion{ +func (p Prompt) ToSessionChatParams() opencode.PartsInputParam { + parts := []opencode.PartsInputItemUnionParam{ opencode.TextPartInputParam{ Type: opencode.F(opencode.TextPartInputTypeText), Text: opencode.F(p.Text), @@ -233,3 +235,62 @@ func (p Prompt) ToSessionChatParams() []opencode.SessionChatParamsPartUnion { } return parts } + +func NewPromptFromParts(parts opencode.PartsInputParam) Prompt { + texts := []string{} + attachments := []*attachment.Attachment{} + for _, part := range parts { + switch p := part.(type) { + case opencode.TextPartInputParam: + texts = append(texts, p.Text.Value) + case opencode.FilePartInputParam: + switch source := p.Source.Value.(type) { + case opencode.FileSourceParam: + display := source.Text.Value.Value.Value + texts = append(texts, display) + attachments = append(attachments, &attachment.Attachment{ + ID: uuid.NewString(), + Type: "file", + Display: display, + URL: p.URL.Value, + Filename: p.Filename.Value, + MediaType: p.Mime.Value, + StartIndex: int(source.Text.Value.Start.Value), + EndIndex: int(source.Text.Value.End.Value), + Source: attachment.FileSource{Path: source.Path.Value, Mime: p.Mime.Value}, + }) + case opencode.SymbolSourceParam: + display := source.Text.Value.Value.Value + texts = append(texts, display) + attachments = append(attachments, &attachment.Attachment{ + ID: uuid.NewString(), + Type: "symbol", + Display: display, + URL: p.URL.Value, + Filename: p.Filename.Value, + MediaType: p.Mime.Value, + StartIndex: int(source.Text.Value.Start.Value), + EndIndex: int(source.Text.Value.End.Value), + Source: attachment.SymbolSource{ + Path: source.Path.Value, + Name: source.Name.Value, + Kind: int(source.Kind.Value), + Range: attachment.SymbolRange{ + Start: attachment.Position{ + Line: int(source.Range.Value.Start.Value.Line.Value), + Char: int(source.Range.Value.Start.Value.Character.Value), + }, + End: attachment.Position{ + Line: int(source.Range.Value.End.Value.Line.Value), + Char: int(source.Range.Value.End.Value.Character.Value), + }, + }}, + }) + } + } + } + return Prompt{ + Text: strings.Join(texts, " "), + Attachments: attachments, + } +} diff --git a/packages/tui/internal/components/chat/editor.go b/packages/tui/internal/components/chat/editor.go index cdae954e6..a629044f8 100644 --- a/packages/tui/internal/components/chat/editor.go +++ b/packages/tui/internal/components/chat/editor.go @@ -45,6 +45,7 @@ type EditorComponent interface { SetInterruptKeyInDebounce(inDebounce bool) SetExitKeyInDebounce(inDebounce bool) RestoreFromHistory(index int) + AppendPrompt(prompt app.Prompt) } type editorComponent struct { @@ -630,21 +631,15 @@ func NewEditorComponent(app *app.App) EditorComponent { return m } -// RestoreFromHistory restores a message from history at the given index -func (m *editorComponent) RestoreFromHistory(index int) { - if index < 0 || index >= len(m.app.State.MessageHistory) { - return - } - - entry := m.app.State.MessageHistory[index] - - m.textarea.Reset() - m.textarea.SetValue(entry.Text) +func (m *editorComponent) AppendPrompt(prompt app.Prompt) { + length := m.Length() + m.textarea.MoveToEnd() + m.textarea.InsertRunesFromUserInput([]rune(prompt.Text)) // Sort attachments by start index in reverse order (process from end to beginning) // This prevents index shifting issues - attachmentsCopy := make([]*attachment.Attachment, len(entry.Attachments)) - copy(attachmentsCopy, entry.Attachments) + attachmentsCopy := make([]*attachment.Attachment, len(prompt.Attachments)) + copy(attachmentsCopy, prompt.Attachments) for i := 0; i < len(attachmentsCopy)-1; i++ { for j := i + 1; j < len(attachmentsCopy); j++ { @@ -655,12 +650,27 @@ func (m *editorComponent) RestoreFromHistory(index int) { } for _, att := range attachmentsCopy { - m.textarea.SetCursorColumn(att.StartIndex) - m.textarea.ReplaceRange(att.StartIndex, att.EndIndex, "") + m.textarea.SetCursorColumn(length + att.StartIndex) + m.textarea.ReplaceRange(length+att.StartIndex, length+att.EndIndex, "") m.textarea.InsertAttachment(att) } } +func (m *editorComponent) RestoreFromPrompt(prompt app.Prompt) { + m.textarea.Reset() + m.textarea.MoveToBegin() + m.AppendPrompt(prompt) +} + +// RestoreFromHistory restores a message from history at the given index +func (m *editorComponent) RestoreFromHistory(index int) { + if index < 0 || index >= len(m.app.State.MessageHistory) { + return + } + entry := m.app.State.MessageHistory[index] + m.RestoreFromPrompt(entry) +} + func getMediaTypeFromExtension(ext string) string { switch strings.ToLower(ext) { case ".jpg": diff --git a/packages/tui/internal/tui/tui.go b/packages/tui/internal/tui/tui.go index 752e805ea..4fc51e78b 100644 --- a/packages/tui/internal/tui/tui.go +++ b/packages/tui/internal/tui/tui.go @@ -511,15 +511,11 @@ func (a Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { a.modal = helpDialog case "/tui/append-prompt": var body struct { - Text string `json:"text"` + Parts opencode.PartsInputParam `json:"parts"` } json.Unmarshal((msg.Body), &body) - existing := a.editor.Value() - text := body.Text - if existing != "" && !strings.HasSuffix(existing, " ") { - text = " " + text - } - a.editor.SetValueWithAttachments(existing + text + " ") + prompt := app.NewPromptFromParts(body.Parts) + a.editor.AppendPrompt(prompt) default: break } diff --git a/packages/tui/sdk/.stats.yml b/packages/tui/sdk/.stats.yml index f9f86831f..d4064bf8b 100644 --- a/packages/tui/sdk/.stats.yml +++ b/packages/tui/sdk/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 24 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/opencode%2Fopencode-9574184bd9e916aa69eae8e26e0679556038d3fcfb4009a445c97c6cc3e4f3ee.yml -openapi_spec_hash: 93ba1215ab0dc853a1691b049cc47d75 -config_hash: 09e4835d57ec7ed0b2d316c6815bcf0a +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/opencode%2Fopencode-305a02cb514ed54609aa9daae92410230435b7f886f04f790b1db828cd20e524.yml +openapi_spec_hash: b207cc749da156457a2b48c9337aa690 +config_hash: 14ba54419d8428bd5440fd20eba04f99 diff --git a/packages/tui/sdk/api.md b/packages/tui/sdk/api.md index 1f5191cad..a72dc643c 100644 --- a/packages/tui/sdk/api.md +++ b/packages/tui/sdk/api.md @@ -79,6 +79,7 @@ Params Types: - opencode.FilePartSourceUnionParam - opencode.FilePartSourceTextParam - opencode.FileSourceParam +- opencode.PartsInputParam - opencode.SymbolSourceParam - opencode.TextPartInputParam diff --git a/packages/tui/sdk/config.go b/packages/tui/sdk/config.go index 0461cba87..e30a929a5 100644 --- a/packages/tui/sdk/config.go +++ b/packages/tui/sdk/config.go @@ -333,7 +333,7 @@ type ConfigProvider struct { Env []string `json:"env"` Name string `json:"name"` Npm string `json:"npm"` - Options map[string]interface{} `json:"options"` + Options ConfigProviderOptions `json:"options"` JSON configProviderJSON `json:"-"` } @@ -447,6 +447,30 @@ func (r configProviderModelsLimitJSON) RawJSON() string { return r.raw } +type ConfigProviderOptions struct { + APIKey string `json:"apiKey"` + BaseURL string `json:"baseURL"` + ExtraFields map[string]interface{} `json:"-,extras"` + JSON configProviderOptionsJSON `json:"-"` +} + +// configProviderOptionsJSON contains the JSON metadata for the struct +// [ConfigProviderOptions] +type configProviderOptionsJSON struct { + APIKey apijson.Field + BaseURL apijson.Field + raw string + ExtraFields map[string]apijson.Field +} + +func (r *ConfigProviderOptions) UnmarshalJSON(data []byte) (err error) { + return apijson.UnmarshalRoot(data, r) +} + +func (r configProviderOptionsJSON) RawJSON() string { + return r.raw +} + // Control sharing behavior:'manual' allows manual sharing via commands, 'auto' // enables automatic sharing, 'disabled' disables all sharing type ConfigShare string diff --git a/packages/tui/sdk/session.go b/packages/tui/sdk/session.go index 8426b64eb..5c78aefa2 100644 --- a/packages/tui/sdk/session.go +++ b/packages/tui/sdk/session.go @@ -496,7 +496,7 @@ func (r FilePartInputParam) MarshalJSON() (data []byte, err error) { return apijson.MarshalRoot(r) } -func (r FilePartInputParam) implementsSessionChatParamsPartUnion() {} +func (r FilePartInputParam) implementsPartsInputItemUnionParam() {} type FilePartInputType string @@ -932,6 +932,46 @@ func (r PartType) IsKnown() bool { return false } +type PartsInputParam []PartsInputItemUnionParam + +type PartsInputItemParam struct { + Type param.Field[PartsInputItemType] `json:"type,required"` + ID param.Field[string] `json:"id"` + Filename param.Field[string] `json:"filename"` + Mime param.Field[string] `json:"mime"` + Source param.Field[FilePartSourceUnionParam] `json:"source"` + Synthetic param.Field[bool] `json:"synthetic"` + Text param.Field[string] `json:"text"` + Time param.Field[interface{}] `json:"time"` + URL param.Field[string] `json:"url"` +} + +func (r PartsInputItemParam) MarshalJSON() (data []byte, err error) { + return apijson.MarshalRoot(r) +} + +func (r PartsInputItemParam) implementsPartsInputItemUnionParam() {} + +// Satisfied by [TextPartInputParam], [FilePartInputParam], [PartsInputItemParam]. +type PartsInputItemUnionParam interface { + implementsPartsInputItemUnionParam() +} + +type PartsInputItemType string + +const ( + PartsInputItemTypeText PartsInputItemType = "text" + PartsInputItemTypeFile PartsInputItemType = "file" +) + +func (r PartsInputItemType) IsKnown() bool { + switch r { + case PartsInputItemTypeText, PartsInputItemTypeFile: + return true + } + return false +} + type Session struct { ID string `json:"id,required"` Time SessionTime `json:"time,required"` @@ -1451,7 +1491,7 @@ func (r TextPartInputParam) MarshalJSON() (data []byte, err error) { return apijson.MarshalRoot(r) } -func (r TextPartInputParam) implementsSessionChatParamsPartUnion() {} +func (r TextPartInputParam) implementsPartsInputItemUnionParam() {} type TextPartInputType string @@ -1949,57 +1989,18 @@ func (r sessionMessagesResponseJSON) RawJSON() string { } type SessionChatParams struct { - ModelID param.Field[string] `json:"modelID,required"` - Parts param.Field[[]SessionChatParamsPartUnion] `json:"parts,required"` - ProviderID param.Field[string] `json:"providerID,required"` - MessageID param.Field[string] `json:"messageID"` - Mode param.Field[string] `json:"mode"` - Tools param.Field[map[string]bool] `json:"tools"` + ModelID param.Field[string] `json:"modelID,required"` + Parts param.Field[PartsInputParam] `json:"parts,required"` + ProviderID param.Field[string] `json:"providerID,required"` + MessageID param.Field[string] `json:"messageID"` + Mode param.Field[string] `json:"mode"` + Tools param.Field[map[string]bool] `json:"tools"` } func (r SessionChatParams) MarshalJSON() (data []byte, err error) { return apijson.MarshalRoot(r) } -type SessionChatParamsPart struct { - Type param.Field[SessionChatParamsPartsType] `json:"type,required"` - ID param.Field[string] `json:"id"` - Filename param.Field[string] `json:"filename"` - Mime param.Field[string] `json:"mime"` - Source param.Field[FilePartSourceUnionParam] `json:"source"` - Synthetic param.Field[bool] `json:"synthetic"` - Text param.Field[string] `json:"text"` - Time param.Field[interface{}] `json:"time"` - URL param.Field[string] `json:"url"` -} - -func (r SessionChatParamsPart) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) -} - -func (r SessionChatParamsPart) implementsSessionChatParamsPartUnion() {} - -// Satisfied by [TextPartInputParam], [FilePartInputParam], -// [SessionChatParamsPart]. -type SessionChatParamsPartUnion interface { - implementsSessionChatParamsPartUnion() -} - -type SessionChatParamsPartsType string - -const ( - SessionChatParamsPartsTypeText SessionChatParamsPartsType = "text" - SessionChatParamsPartsTypeFile SessionChatParamsPartsType = "file" -) - -func (r SessionChatParamsPartsType) IsKnown() bool { - switch r { - case SessionChatParamsPartsTypeText, SessionChatParamsPartsTypeFile: - return true - } - return false -} - type SessionInitParams struct { MessageID param.Field[string] `json:"messageID,required"` ModelID param.Field[string] `json:"modelID,required"` diff --git a/packages/tui/sdk/session_test.go b/packages/tui/sdk/session_test.go index 5d7c55cad..59c28d01a 100644 --- a/packages/tui/sdk/session_test.go +++ b/packages/tui/sdk/session_test.go @@ -118,7 +118,7 @@ func TestSessionChatWithOptionalParams(t *testing.T) { "id", opencode.SessionChatParams{ ModelID: opencode.F("modelID"), - Parts: opencode.F([]opencode.SessionChatParamsPartUnion{opencode.TextPartInputParam{ + Parts: opencode.F(opencode.PartsInputParam{opencode.TextPartInputParam{ Text: opencode.F("text"), Type: opencode.F(opencode.TextPartInputTypeText), ID: opencode.F("id"), diff --git a/packages/tui/sdk/tui.go b/packages/tui/sdk/tui.go index d5243599f..74652f7fa 100644 --- a/packages/tui/sdk/tui.go +++ b/packages/tui/sdk/tui.go @@ -48,7 +48,7 @@ func (r *TuiService) OpenHelp(ctx context.Context, opts ...option.RequestOption) } type TuiAppendPromptParams struct { - Text param.Field[string] `json:"text,required"` + Parts param.Field[PartsInputParam] `json:"parts,required"` } func (r TuiAppendPromptParams) MarshalJSON() (data []byte, err error) { diff --git a/packages/tui/sdk/tui_test.go b/packages/tui/sdk/tui_test.go index 5283f37c5..f05e961fe 100644 --- a/packages/tui/sdk/tui_test.go +++ b/packages/tui/sdk/tui_test.go @@ -26,7 +26,16 @@ func TestTuiAppendPrompt(t *testing.T) { option.WithBaseURL(baseURL), ) _, err := client.Tui.AppendPrompt(context.TODO(), opencode.TuiAppendPromptParams{ - Text: opencode.F("text"), + Parts: opencode.F(opencode.PartsInputParam{opencode.TextPartInputParam{ + Text: opencode.F("text"), + Type: opencode.F(opencode.TextPartInputTypeText), + ID: opencode.F("id"), + Synthetic: opencode.F(true), + Time: opencode.F(opencode.TextPartInputTimeParam{ + Start: opencode.F(0.000000), + End: opencode.F(0.000000), + }), + }}), }) if err != nil { var apierr *opencode.Error diff --git a/sdks/vscode/src/extension.ts b/sdks/vscode/src/extension.ts index 49a05f641..ebe42a147 100644 --- a/sdks/vscode/src/extension.ts +++ b/sdks/vscode/src/extension.ts @@ -77,7 +77,7 @@ async function appendPrompt(port: number, text: string) { headers: { "Content-Type": "application/json", }, - body: JSON.stringify({ text }), + body: JSON.stringify({ parts: [{ type: "text", text }] }), }) } diff --git a/stainless.yml b/stainless.yml index 317238438..f5275753f 100644 --- a/stainless.yml +++ b/stainless.yml @@ -90,6 +90,7 @@ resources: session: Session message: Message part: Part + partsInput: PartsInput textPart: TextPart textPartInput: TextPartInput filePart: FilePart