Skip to content

Commit 5aafab1

Browse files
committed
wip: tui api
1 parent 01f8d3b commit 5aafab1

13 files changed

Lines changed: 109 additions & 396 deletions

File tree

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { Server } from "../../server/server"
22
import fs from "fs/promises"
3-
import path from "path"
43
import type { CommandModule } from "yargs"
54

65
export const GenerateCommand = {
@@ -10,6 +9,6 @@ export const GenerateCommand = {
109
const dir = "gen"
1110
await fs.rmdir(dir, { recursive: true }).catch(() => {})
1211
await fs.mkdir(dir, { recursive: true })
13-
await Bun.write(path.join(dir, "openapi.json"), JSON.stringify(specs, null, 2))
12+
process.stdout.write(JSON.stringify(specs, null, 2))
1413
},
1514
} satisfies CommandModule

packages/opencode/src/server/server.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -705,9 +705,9 @@ export namespace Server {
705705
},
706706
)
707707
.post(
708-
"/tui/prompt",
708+
"/tui/append-prompt",
709709
describeRoute({
710-
description: "Send a prompt to the TUI",
710+
description: "Append prompt to the TUI",
711711
responses: {
712712
200: {
713713
description: "Prompt processed successfully",
@@ -723,7 +723,6 @@ export namespace Server {
723723
"json",
724724
z.object({
725725
text: z.string(),
726-
parts: MessageV2.Part.array(),
727726
}),
728727
),
729728
async (c) => c.json(await callTui(c)),

packages/tui/internal/components/chat/editor.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -486,7 +486,9 @@ func (m *editorComponent) SetValueWithAttachments(value string) {
486486

487487
if end > start {
488488
filePath := value[start:end]
489-
if _, err := os.Stat(filePath); err == nil {
489+
slog.Debug("test", "filePath", filePath)
490+
if _, err := os.Stat(filepath.Join(m.app.Info.Path.Cwd, filePath)); err == nil {
491+
slog.Debug("test", "found", true)
490492
attachment := m.createAttachmentFromFile(filePath)
491493
if attachment != nil {
492494
m.textarea.InsertAttachment(attachment)

packages/tui/internal/tui/tui.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -509,13 +509,13 @@ func (a Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
509509
case "/tui/open-help":
510510
helpDialog := dialog.NewHelpDialog(a.app)
511511
a.modal = helpDialog
512-
case "/tui/prompt":
512+
case "/tui/append-prompt":
513513
var body struct {
514514
Text string `json:"text"`
515515
Parts []opencode.Part `json:"parts"`
516516
}
517517
json.Unmarshal((msg.Body), &body)
518-
a.editor.SetValue(body.Text)
518+
a.editor.SetValueWithAttachments(strings.TrimRight(a.editor.Value(), " ") + " " + body.Text + " ")
519519
default:
520520
break
521521
}

packages/tui/sdk/.stats.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
configured_endpoints: 24
2-
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/opencode%2Fopencode-d10809ab68e48a338167e5504d69db2a0a80739adf6ecd3f065644a4139bc374.yml
3-
openapi_spec_hash: 4875565ef8df3446dbab11f450e04c51
4-
config_hash: 0032a76356d31c6b4c218b39fff635bb
2+
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/opencode%2Fopencode-9574184bd9e916aa69eae8e26e0679556038d3fcfb4009a445c97c6cc3e4f3ee.yml
3+
openapi_spec_hash: 93ba1215ab0dc853a1691b049cc47d75
4+
config_hash: 6d92d798d44906c9e43c6dee06615360

packages/tui/sdk/api.md

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -75,23 +75,12 @@ Methods:
7575

7676
Params Types:
7777

78-
- <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>
7978
- <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#FilePartInputParam">FilePartInputParam</a>
8079
- <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>
8180
- <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>
8281
- <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>
83-
- <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#PartUnionParam">PartUnionParam</a>
84-
- <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#SnapshotPartParam">SnapshotPartParam</a>
85-
- <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#StepFinishPartParam">StepFinishPartParam</a>
86-
- <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>
8782
- <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>
88-
- <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>
8983
- <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>
90-
- <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#ToolPartParam">ToolPartParam</a>
91-
- <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#ToolStateCompletedParam">ToolStateCompletedParam</a>
92-
- <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#ToolStateErrorParam">ToolStateErrorParam</a>
93-
- <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#ToolStatePendingParam">ToolStatePendingParam</a>
94-
- <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#ToolStateRunningParam">ToolStateRunningParam</a>
9584

9685
Response Types:
9786

@@ -133,5 +122,5 @@ Methods:
133122

134123
Methods:
135124

125+
- <code title="post /tui/append-prompt">client.Tui.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#TuiService.AppendPrompt">AppendPrompt</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</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#TuiAppendPromptParams">TuiAppendPromptParams</a>) (<a href="https://pkg.go.dev/builtin#bool">bool</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
136126
- <code title="post /tui/open-help">client.Tui.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#TuiService.OpenHelp">OpenHelp</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/builtin#bool">bool</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
137-
- <code title="post /tui/prompt">client.Tui.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#TuiService.Prompt">Prompt</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</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#TuiPromptParams">TuiPromptParams</a>) (<a href="https://pkg.go.dev/builtin#bool">bool</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>

packages/tui/sdk/event.go

Lines changed: 73 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@ type EventListResponse struct {
5252
// [EventListResponseEventPermissionUpdatedProperties],
5353
// [EventListResponseEventFileEditedProperties],
5454
// [EventListResponseEventInstallationUpdatedProperties],
55-
// [EventListResponseEventIdeInstalledProperties],
5655
// [EventListResponseEventMessageUpdatedProperties],
5756
// [EventListResponseEventMessageRemovedProperties],
5857
// [EventListResponseEventMessagePartUpdatedProperties],
@@ -61,7 +60,8 @@ type EventListResponse struct {
6160
// [EventListResponseEventSessionDeletedProperties],
6261
// [EventListResponseEventSessionIdleProperties],
6362
// [EventListResponseEventSessionErrorProperties],
64-
// [EventListResponseEventFileWatcherUpdatedProperties].
63+
// [EventListResponseEventFileWatcherUpdatedProperties],
64+
// [EventListResponseEventIdeInstalledProperties].
6565
Properties interface{} `json:"properties,required"`
6666
Type EventListResponseType `json:"type,required"`
6767
JSON eventListResponseJSON `json:"-"`
@@ -97,27 +97,26 @@ func (r *EventListResponse) UnmarshalJSON(data []byte) (err error) {
9797
// [EventListResponseEventLspClientDiagnostics],
9898
// [EventListResponseEventPermissionUpdated], [EventListResponseEventFileEdited],
9999
// [EventListResponseEventInstallationUpdated],
100-
// [EventListResponseEventIdeInstalled],
101100
// [EventListResponseEventMessageUpdated], [EventListResponseEventMessageRemoved],
102101
// [EventListResponseEventMessagePartUpdated],
103102
// [EventListResponseEventStorageWrite], [EventListResponseEventSessionUpdated],
104103
// [EventListResponseEventSessionDeleted], [EventListResponseEventSessionIdle],
105104
// [EventListResponseEventSessionError],
106-
// [EventListResponseEventFileWatcherUpdated].
105+
// [EventListResponseEventFileWatcherUpdated],
106+
// [EventListResponseEventIdeInstalled].
107107
func (r EventListResponse) AsUnion() EventListResponseUnion {
108108
return r.union
109109
}
110110

111111
// Union satisfied by [EventListResponseEventLspClientDiagnostics],
112112
// [EventListResponseEventPermissionUpdated], [EventListResponseEventFileEdited],
113113
// [EventListResponseEventInstallationUpdated],
114-
// [EventListResponseEventIdeInstalled],
115114
// [EventListResponseEventMessageUpdated], [EventListResponseEventMessageRemoved],
116115
// [EventListResponseEventMessagePartUpdated],
117116
// [EventListResponseEventStorageWrite], [EventListResponseEventSessionUpdated],
118117
// [EventListResponseEventSessionDeleted], [EventListResponseEventSessionIdle],
119-
// [EventListResponseEventSessionError] or
120-
// [EventListResponseEventFileWatcherUpdated].
118+
// [EventListResponseEventSessionError], [EventListResponseEventFileWatcherUpdated]
119+
// or [EventListResponseEventIdeInstalled].
121120
type EventListResponseUnion interface {
122121
implementsEventListResponse()
123122
}
@@ -146,11 +145,6 @@ func init() {
146145
Type: reflect.TypeOf(EventListResponseEventInstallationUpdated{}),
147146
DiscriminatorValue: "installation.updated",
148147
},
149-
apijson.UnionVariant{
150-
TypeFilter: gjson.JSON,
151-
Type: reflect.TypeOf(EventListResponseEventIdeInstalled{}),
152-
DiscriminatorValue: "ide.installed",
153-
},
154148
apijson.UnionVariant{
155149
TypeFilter: gjson.JSON,
156150
Type: reflect.TypeOf(EventListResponseEventMessageUpdated{}),
@@ -196,6 +190,11 @@ func init() {
196190
Type: reflect.TypeOf(EventListResponseEventFileWatcherUpdated{}),
197191
DiscriminatorValue: "file.watcher.updated",
198192
},
193+
apijson.UnionVariant{
194+
TypeFilter: gjson.JSON,
195+
Type: reflect.TypeOf(EventListResponseEventIdeInstalled{}),
196+
DiscriminatorValue: "ide.installed",
197+
},
199198
)
200199
}
201200

@@ -470,66 +469,6 @@ func (r EventListResponseEventInstallationUpdatedType) IsKnown() bool {
470469
return false
471470
}
472471

473-
type EventListResponseEventIdeInstalled struct {
474-
Properties EventListResponseEventIdeInstalledProperties `json:"properties,required"`
475-
Type EventListResponseEventIdeInstalledType `json:"type,required"`
476-
JSON eventListResponseEventIdeInstalledJSON `json:"-"`
477-
}
478-
479-
// eventListResponseEventIdeInstalledJSON contains the JSON metadata for the
480-
// struct [EventListResponseEventIdeInstalled]
481-
type eventListResponseEventIdeInstalledJSON struct {
482-
Properties apijson.Field
483-
Type apijson.Field
484-
raw string
485-
ExtraFields map[string]apijson.Field
486-
}
487-
488-
func (r *EventListResponseEventIdeInstalled) UnmarshalJSON(data []byte) (err error) {
489-
return apijson.UnmarshalRoot(data, r)
490-
}
491-
492-
func (r eventListResponseEventIdeInstalledJSON) RawJSON() string {
493-
return r.raw
494-
}
495-
496-
func (r EventListResponseEventIdeInstalled) implementsEventListResponse() {}
497-
498-
type EventListResponseEventIdeInstalledProperties struct {
499-
Ide string `json:"ide,required"`
500-
JSON eventListResponseEventIdeInstalledPropertiesJSON `json:"-"`
501-
}
502-
503-
// eventListResponseEventIdeInstalledPropertiesJSON contains the JSON
504-
// metadata for the struct [EventListResponseEventIdeInstalledProperties]
505-
type eventListResponseEventIdeInstalledPropertiesJSON struct {
506-
Ide apijson.Field
507-
raw string
508-
ExtraFields map[string]apijson.Field
509-
}
510-
511-
func (r *EventListResponseEventIdeInstalledProperties) UnmarshalJSON(data []byte) (err error) {
512-
return apijson.UnmarshalRoot(data, r)
513-
}
514-
515-
func (r eventListResponseEventIdeInstalledPropertiesJSON) RawJSON() string {
516-
return r.raw
517-
}
518-
519-
type EventListResponseEventIdeInstalledType string
520-
521-
const (
522-
EventListResponseEventIdeInstalledTypeIdeInstalled EventListResponseEventIdeInstalledType = "ide.installed"
523-
)
524-
525-
func (r EventListResponseEventIdeInstalledType) IsKnown() bool {
526-
switch r {
527-
case EventListResponseEventIdeInstalledTypeIdeInstalled:
528-
return true
529-
}
530-
return false
531-
}
532-
533472
type EventListResponseEventMessageUpdated struct {
534473
Properties EventListResponseEventMessageUpdatedProperties `json:"properties,required"`
535474
Type EventListResponseEventMessageUpdatedType `json:"type,required"`
@@ -1227,14 +1166,73 @@ func (r EventListResponseEventFileWatcherUpdatedType) IsKnown() bool {
12271166
return false
12281167
}
12291168

1169+
type EventListResponseEventIdeInstalled struct {
1170+
Properties EventListResponseEventIdeInstalledProperties `json:"properties,required"`
1171+
Type EventListResponseEventIdeInstalledType `json:"type,required"`
1172+
JSON eventListResponseEventIdeInstalledJSON `json:"-"`
1173+
}
1174+
1175+
// eventListResponseEventIdeInstalledJSON contains the JSON metadata for the struct
1176+
// [EventListResponseEventIdeInstalled]
1177+
type eventListResponseEventIdeInstalledJSON struct {
1178+
Properties apijson.Field
1179+
Type apijson.Field
1180+
raw string
1181+
ExtraFields map[string]apijson.Field
1182+
}
1183+
1184+
func (r *EventListResponseEventIdeInstalled) UnmarshalJSON(data []byte) (err error) {
1185+
return apijson.UnmarshalRoot(data, r)
1186+
}
1187+
1188+
func (r eventListResponseEventIdeInstalledJSON) RawJSON() string {
1189+
return r.raw
1190+
}
1191+
1192+
func (r EventListResponseEventIdeInstalled) implementsEventListResponse() {}
1193+
1194+
type EventListResponseEventIdeInstalledProperties struct {
1195+
Ide string `json:"ide,required"`
1196+
JSON eventListResponseEventIdeInstalledPropertiesJSON `json:"-"`
1197+
}
1198+
1199+
// eventListResponseEventIdeInstalledPropertiesJSON contains the JSON metadata for
1200+
// the struct [EventListResponseEventIdeInstalledProperties]
1201+
type eventListResponseEventIdeInstalledPropertiesJSON struct {
1202+
Ide apijson.Field
1203+
raw string
1204+
ExtraFields map[string]apijson.Field
1205+
}
1206+
1207+
func (r *EventListResponseEventIdeInstalledProperties) UnmarshalJSON(data []byte) (err error) {
1208+
return apijson.UnmarshalRoot(data, r)
1209+
}
1210+
1211+
func (r eventListResponseEventIdeInstalledPropertiesJSON) RawJSON() string {
1212+
return r.raw
1213+
}
1214+
1215+
type EventListResponseEventIdeInstalledType string
1216+
1217+
const (
1218+
EventListResponseEventIdeInstalledTypeIdeInstalled EventListResponseEventIdeInstalledType = "ide.installed"
1219+
)
1220+
1221+
func (r EventListResponseEventIdeInstalledType) IsKnown() bool {
1222+
switch r {
1223+
case EventListResponseEventIdeInstalledTypeIdeInstalled:
1224+
return true
1225+
}
1226+
return false
1227+
}
1228+
12301229
type EventListResponseType string
12311230

12321231
const (
12331232
EventListResponseTypeLspClientDiagnostics EventListResponseType = "lsp.client.diagnostics"
12341233
EventListResponseTypePermissionUpdated EventListResponseType = "permission.updated"
12351234
EventListResponseTypeFileEdited EventListResponseType = "file.edited"
12361235
EventListResponseTypeInstallationUpdated EventListResponseType = "installation.updated"
1237-
EventListResponseTypeIdeInstalled EventListResponseType = "ide.installed"
12381236
EventListResponseTypeMessageUpdated EventListResponseType = "message.updated"
12391237
EventListResponseTypeMessageRemoved EventListResponseType = "message.removed"
12401238
EventListResponseTypeMessagePartUpdated EventListResponseType = "message.part.updated"
@@ -1244,11 +1242,12 @@ const (
12441242
EventListResponseTypeSessionIdle EventListResponseType = "session.idle"
12451243
EventListResponseTypeSessionError EventListResponseType = "session.error"
12461244
EventListResponseTypeFileWatcherUpdated EventListResponseType = "file.watcher.updated"
1245+
EventListResponseTypeIdeInstalled EventListResponseType = "ide.installed"
12471246
)
12481247

12491248
func (r EventListResponseType) IsKnown() bool {
12501249
switch r {
1251-
case EventListResponseTypeLspClientDiagnostics, EventListResponseTypePermissionUpdated, EventListResponseTypeFileEdited, EventListResponseTypeInstallationUpdated, EventListResponseTypeIdeInstalled, EventListResponseTypeMessageUpdated, EventListResponseTypeMessageRemoved, EventListResponseTypeMessagePartUpdated, EventListResponseTypeStorageWrite, EventListResponseTypeSessionUpdated, EventListResponseTypeSessionDeleted, EventListResponseTypeSessionIdle, EventListResponseTypeSessionError, EventListResponseTypeFileWatcherUpdated:
1250+
case EventListResponseTypeLspClientDiagnostics, EventListResponseTypePermissionUpdated, EventListResponseTypeFileEdited, EventListResponseTypeInstallationUpdated, EventListResponseTypeMessageUpdated, EventListResponseTypeMessageRemoved, EventListResponseTypeMessagePartUpdated, EventListResponseTypeStorageWrite, EventListResponseTypeSessionUpdated, EventListResponseTypeSessionDeleted, EventListResponseTypeSessionIdle, EventListResponseTypeSessionError, EventListResponseTypeFileWatcherUpdated, EventListResponseTypeIdeInstalled:
12521251
return true
12531252
}
12541253
return false

packages/tui/sdk/option/requestoption.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,15 @@ type RequestOption = requestconfig.RequestOption
2727
// For security reasons, ensure that the base URL is trusted.
2828
func WithBaseURL(base string) RequestOption {
2929
u, err := url.Parse(base)
30+
if err == nil && u.Path != "" && !strings.HasSuffix(u.Path, "/") {
31+
u.Path += "/"
32+
}
33+
3034
return requestconfig.RequestOptionFunc(func(r *requestconfig.RequestConfig) error {
3135
if err != nil {
32-
return fmt.Errorf("requestoption: WithBaseURL failed to parse url %s\n", err)
36+
return fmt.Errorf("requestoption: WithBaseURL failed to parse url %s", err)
3337
}
3438

35-
if u.Path != "" && !strings.HasSuffix(u.Path, "/") {
36-
u.Path += "/"
37-
}
3839
r.BaseURL = u
3940
return nil
4041
})

0 commit comments

Comments
 (0)