mirror of
https://github.com/sst/opencode.git
synced 2025-12-23 10:11:41 +00:00
wip: append prompt
This commit is contained in:
parent
b7b0cdbd7c
commit
7e4c6095ec
22 changed files with 225 additions and 103 deletions
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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<typeof ChatInput>
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -92,6 +92,7 @@ Types:
|
|||
- <code><a href="./src/resources/session.ts">FileSource</a></code>
|
||||
- <code><a href="./src/resources/session.ts">Message</a></code>
|
||||
- <code><a href="./src/resources/session.ts">Part</a></code>
|
||||
- <code><a href="./src/resources/session.ts">PartsInput</a></code>
|
||||
- <code><a href="./src/resources/session.ts">Session</a></code>
|
||||
- <code><a href="./src/resources/session.ts">SnapshotPart</a></code>
|
||||
- <code><a href="./src/resources/session.ts">StepFinishPart</a></code>
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ export {
|
|||
type FileSource,
|
||||
type Message,
|
||||
type Part,
|
||||
type PartsInput,
|
||||
type Session,
|
||||
type SnapshotPart,
|
||||
type StepFinishPart,
|
||||
|
|
|
|||
|
|
@ -205,6 +205,8 @@ export type Message = UserMessage | AssistantMessage;
|
|||
|
||||
export type Part = TextPart | FilePart | ToolPart | StepStartPart | StepFinishPart | SnapshotPart;
|
||||
|
||||
export type PartsInput = Array<TextPartInput | FilePartInput>;
|
||||
|
||||
export interface Session {
|
||||
id: string;
|
||||
|
||||
|
|
@ -494,7 +496,7 @@ export type SessionSummarizeResponse = boolean;
|
|||
export interface SessionChatParams {
|
||||
modelID: string;
|
||||
|
||||
parts: Array<TextPartInput | FilePartInput>;
|
||||
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,
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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":
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -79,6 +79,7 @@ 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#FilePartSourceUnionParam">FilePartSourceUnionParam</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#FilePartSourceTextParam">FilePartSourceTextParam</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#FileSourceParam">FileSourceParam</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#PartsInputParam">PartsInputParam</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#SymbolSourceParam">SymbolSourceParam</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#TextPartInputParam">TextPartInputParam</a>
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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"`
|
||||
|
|
|
|||
|
|
@ -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"),
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 }] }),
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ resources:
|
|||
session: Session
|
||||
message: Message
|
||||
part: Part
|
||||
partsInput: PartsInput
|
||||
textPart: TextPart
|
||||
textPartInput: TextPartInput
|
||||
filePart: FilePart
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue