summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authoradamdottv <[email protected]>2025-07-09 08:16:10 -0500
committeradamdottv <[email protected]>2025-07-09 08:16:10 -0500
commitca8ce88354fa2f8e7cc8f0a911197a2550ebc269 (patch)
tree07902e77aadb66113897c8363488d0b3a90ebf5d
parent37a86439c426bc735e3b3e76767ddd4c321fbe1a (diff)
downloadopencode-ca8ce88354fa2f8e7cc8f0a911197a2550ebc269.tar.gz
opencode-ca8ce88354fa2f8e7cc8f0a911197a2550ebc269.zip
feat(tui): move logging to server logs
-rw-r--r--packages/opencode/src/file/index.ts23
-rw-r--r--packages/opencode/src/file/ripgrep.ts38
-rw-r--r--packages/opencode/src/lsp/index.ts2
-rw-r--r--packages/opencode/src/server/server.ts57
-rw-r--r--packages/opencode/src/util/log.ts32
-rw-r--r--packages/tui/cmd/opencode/main.go30
-rw-r--r--packages/tui/internal/completions/files-folders.go4
-rw-r--r--packages/tui/internal/util/apilogger.go131
-rw-r--r--packages/tui/sdk/.stats.yml8
-rw-r--r--packages/tui/sdk/api.md13
-rw-r--r--packages/tui/sdk/app.go41
-rw-r--r--packages/tui/sdk/app_test.go29
-rw-r--r--packages/tui/sdk/config.go74
-rw-r--r--packages/tui/sdk/event.go6
-rw-r--r--packages/tui/sdk/file.go75
-rw-r--r--packages/tui/sdk/find.go209
-rw-r--r--packages/tui/sdk/packages/ssestream/ssestream.go2
-rwxr-xr-xpackages/tui/sdk/scripts/lint4
-rw-r--r--stainless.yml6
19 files changed, 582 insertions, 202 deletions
diff --git a/packages/opencode/src/file/index.ts b/packages/opencode/src/file/index.ts
index 1b93ca266..b99f35e1f 100644
--- a/packages/opencode/src/file/index.ts
+++ b/packages/opencode/src/file/index.ts
@@ -11,6 +11,19 @@ import { Log } from "../util/log"
export namespace File {
const log = Log.create({ service: "file" })
+ export const Info = z
+ .object({
+ path: z.string(),
+ added: z.number().int(),
+ removed: z.number().int(),
+ status: z.enum(["added", "deleted", "modified"]),
+ })
+ .openapi({
+ ref: "File",
+ })
+
+ export type Info = z.infer<typeof Info>
+
export const Event = {
Edited: Bus.event(
"file.edited",
@@ -26,14 +39,14 @@ export namespace File {
const diffOutput = await $`git diff --numstat HEAD`.cwd(app.path.cwd).quiet().nothrow().text()
- const changedFiles = []
+ const changedFiles: Info[] = []
if (diffOutput.trim()) {
const lines = diffOutput.trim().split("\n")
for (const line of lines) {
const [added, removed, filepath] = line.split("\t")
changedFiles.push({
- file: filepath,
+ path: filepath,
added: added === "-" ? 0 : parseInt(added, 10),
removed: removed === "-" ? 0 : parseInt(removed, 10),
status: "modified",
@@ -50,7 +63,7 @@ export namespace File {
const content = await Bun.file(path.join(app.path.root, filepath)).text()
const lines = content.split("\n").length
changedFiles.push({
- file: filepath,
+ path: filepath,
added: lines,
removed: 0,
status: "added",
@@ -68,7 +81,7 @@ export namespace File {
const deletedFiles = deletedOutput.trim().split("\n")
for (const filepath of deletedFiles) {
changedFiles.push({
- file: filepath,
+ path: filepath,
added: 0,
removed: 0, // Could get original line count but would require another git command
status: "deleted",
@@ -78,7 +91,7 @@ export namespace File {
return changedFiles.map((x) => ({
...x,
- file: path.relative(app.path.cwd, path.join(app.path.root, x.file)),
+ path: path.relative(app.path.cwd, path.join(app.path.root, x.path)),
}))
}
diff --git a/packages/opencode/src/file/ripgrep.ts b/packages/opencode/src/file/ripgrep.ts
index 07334bc00..05ebbe7d4 100644
--- a/packages/opencode/src/file/ripgrep.ts
+++ b/packages/opencode/src/file/ripgrep.ts
@@ -34,25 +34,27 @@ export namespace Ripgrep {
export const Match = z.object({
type: z.literal("match"),
- data: z.object({
- path: z.object({
- text: z.string(),
- }),
- lines: z.object({
- text: z.string(),
- }),
- line_number: z.number(),
- absolute_offset: z.number(),
- submatches: z.array(
- z.object({
- match: z.object({
- text: z.string(),
- }),
- start: z.number(),
- end: z.number(),
+ data: z
+ .object({
+ path: z.object({
+ text: z.string(),
}),
- ),
- }),
+ lines: z.object({
+ text: z.string(),
+ }),
+ line_number: z.number(),
+ absolute_offset: z.number(),
+ submatches: z.array(
+ z.object({
+ match: z.object({
+ text: z.string(),
+ }),
+ start: z.number(),
+ end: z.number(),
+ }),
+ ),
+ })
+ .openapi({ ref: "Match" }),
})
const End = z.object({
diff --git a/packages/opencode/src/lsp/index.ts b/packages/opencode/src/lsp/index.ts
index f7e33e309..6fea09d79 100644
--- a/packages/opencode/src/lsp/index.ts
+++ b/packages/opencode/src/lsp/index.ts
@@ -28,7 +28,7 @@ export namespace LSP {
}),
})
.openapi({
- ref: "LSP.Symbol",
+ ref: "Symbol",
})
export type Symbol = z.infer<typeof Symbol>
diff --git a/packages/opencode/src/server/server.ts b/packages/opencode/src/server/server.ts
index d7884ca9b..23950cdba 100644
--- a/packages/opencode/src/server/server.ts
+++ b/packages/opencode/src/server/server.ts
@@ -621,16 +621,7 @@ export namespace Server {
description: "File status",
content: {
"application/json": {
- schema: resolver(
- z
- .object({
- file: z.string(),
- added: z.number().int(),
- removed: z.number().int(),
- status: z.enum(["added", "deleted", "modified"]),
- })
- .array(),
- ),
+ schema: resolver(File.Info.array()),
},
},
},
@@ -641,6 +632,52 @@ export namespace Server {
return c.json(content)
},
)
+ .post(
+ "/log",
+ describeRoute({
+ description: "Write a log entry to the server logs",
+ responses: {
+ 200: {
+ description: "Log entry written successfully",
+ content: {
+ "application/json": {
+ schema: resolver(z.boolean()),
+ },
+ },
+ },
+ },
+ }),
+ zValidator(
+ "json",
+ z.object({
+ service: z.string().openapi({ description: "Service name for the log entry" }),
+ level: z.enum(["info", "error", "warn"]).openapi({ description: "Log level" }),
+ message: z.string().openapi({ description: "Log message" }),
+ extra: z
+ .record(z.string(), z.any())
+ .optional()
+ .openapi({ description: "Additional metadata for the log entry" }),
+ }),
+ ),
+ async (c) => {
+ const { service, level, message, extra } = c.req.valid("json")
+ const logger = Log.create({ service })
+
+ switch (level) {
+ case "info":
+ logger.info(message, extra)
+ break
+ case "error":
+ logger.error(message, extra)
+ break
+ case "warn":
+ logger.warn(message, extra)
+ break
+ }
+
+ return c.json(true)
+ },
+ )
return result
}
diff --git a/packages/opencode/src/util/log.ts b/packages/opencode/src/util/log.ts
index 54027c26c..f3928e13e 100644
--- a/packages/opencode/src/util/log.ts
+++ b/packages/opencode/src/util/log.ts
@@ -2,6 +2,23 @@ import path from "path"
import fs from "fs/promises"
import { Global } from "../global"
export namespace Log {
+ export type Logger = {
+ info(message?: any, extra?: Record<string, any>): void
+ error(message?: any, extra?: Record<string, any>): void
+ warn(message?: any, extra?: Record<string, any>): void
+ tag(key: string, value: string): Logger
+ clone(): Logger
+ time(
+ message: string,
+ extra?: Record<string, any>,
+ ): {
+ stop(): void
+ [Symbol.dispose](): void
+ }
+ }
+
+ const loggers = new Map<string, Logger>()
+
export const Default = create({ service: "default" })
export interface Options {
@@ -9,7 +26,6 @@ export namespace Log {
}
let logpath = ""
-
export function file() {
return logpath
}
@@ -47,6 +63,14 @@ export namespace Log {
export function create(tags?: Record<string, any>) {
tags = tags || {}
+ const service = tags["service"]
+ if (service && typeof service === "string") {
+ const cached = loggers.get(service)
+ if (cached) {
+ return cached
+ }
+ }
+
function build(message: any, extra?: Record<string, any>) {
const prefix = Object.entries({
...tags,
@@ -60,7 +84,7 @@ export namespace Log {
last = next.getTime()
return [next.toISOString().split(".")[0], "+" + diff + "ms", prefix, message].filter(Boolean).join(" ") + "\n"
}
- const result = {
+ const result: Logger = {
info(message?: any, extra?: Record<string, any>) {
process.stderr.write("INFO " + build(message, extra))
},
@@ -96,6 +120,10 @@ export namespace Log {
},
}
+ if (service && typeof service === "string") {
+ loggers.set(service, result)
+ }
+
return result
}
}
diff --git a/packages/tui/cmd/opencode/main.go b/packages/tui/cmd/opencode/main.go
index 0c8f70c8b..31ef03e5a 100644
--- a/packages/tui/cmd/opencode/main.go
+++ b/packages/tui/cmd/opencode/main.go
@@ -5,7 +5,6 @@ import (
"encoding/json"
"log/slog"
"os"
- "path/filepath"
"strings"
tea "github.com/charmbracelet/bubbletea/v2"
@@ -15,6 +14,7 @@ import (
"github.com/sst/opencode/internal/app"
"github.com/sst/opencode/internal/clipboard"
"github.com/sst/opencode/internal/tui"
+ "github.com/sst/opencode/internal/util"
)
var Version = "dev"
@@ -39,33 +39,15 @@ func main() {
os.Exit(1)
}
- logfile := filepath.Join(appInfo.Path.Data, "log", "tui.log")
- if _, err := os.Stat(filepath.Dir(logfile)); os.IsNotExist(err) {
- err := os.MkdirAll(filepath.Dir(logfile), 0755)
- if err != nil {
- slog.Error("Failed to create log directory", "error", err)
- os.Exit(1)
- }
- }
- file, err := os.Create(logfile)
- if err != nil {
- slog.Error("Failed to create log file", "error", err)
- os.Exit(1)
- }
- defer file.Close()
- logger := slog.New(slog.NewTextHandler(file, &slog.HandlerOptions{Level: slog.LevelDebug}))
- slog.SetDefault(logger)
-
- slog.Debug("TUI launched", "app", appInfo)
-
httpClient := opencode.NewClient(
option.WithBaseURL(url),
)
- if err != nil {
- slog.Error("Failed to create client", "error", err)
- os.Exit(1)
- }
+ apiHandler := util.NewAPILogHandler(httpClient, "tui", slog.LevelDebug)
+ logger := slog.New(apiHandler)
+ slog.SetDefault(logger)
+
+ slog.Debug("TUI launched", "app", appInfo)
go func() {
err = clipboard.Init()
diff --git a/packages/tui/internal/completions/files-folders.go b/packages/tui/internal/completions/files-folders.go
index ec298af9e..55e0c1a1b 100644
--- a/packages/tui/internal/completions/files-folders.go
+++ b/packages/tui/internal/completions/files-folders.go
@@ -42,7 +42,7 @@ func (cg *filesAndFoldersContextGroup) getGitFiles() []dialog.CompletionItemI {
})
for _, file := range files {
- title := file.File
+ title := file.Path
if file.Added > 0 {
title += green(" +" + strconv.Itoa(int(file.Added)))
}
@@ -51,7 +51,7 @@ func (cg *filesAndFoldersContextGroup) getGitFiles() []dialog.CompletionItemI {
}
item := dialog.NewCompletionItem(dialog.CompletionItem{
Title: title,
- Value: file.File,
+ Value: file.Path,
})
items = append(items, item)
}
diff --git a/packages/tui/internal/util/apilogger.go b/packages/tui/internal/util/apilogger.go
new file mode 100644
index 000000000..11eb21722
--- /dev/null
+++ b/packages/tui/internal/util/apilogger.go
@@ -0,0 +1,131 @@
+package util
+
+import (
+ "context"
+ "log/slog"
+ "sync"
+
+ opencode "github.com/sst/opencode-sdk-go"
+)
+
+// APILogHandler is a slog.Handler that sends logs to the opencode API
+type APILogHandler struct {
+ client *opencode.Client
+ service string
+ level slog.Level
+ attrs []slog.Attr
+ groups []string
+ mu sync.Mutex
+}
+
+// NewAPILogHandler creates a new APILogHandler
+func NewAPILogHandler(client *opencode.Client, service string, level slog.Level) *APILogHandler {
+ return &APILogHandler{
+ client: client,
+ service: service,
+ level: level,
+ attrs: make([]slog.Attr, 0),
+ groups: make([]string, 0),
+ }
+}
+
+// Enabled reports whether the handler handles records at the given level.
+func (h *APILogHandler) Enabled(_ context.Context, level slog.Level) bool {
+ return level >= h.level
+}
+
+// Handle handles the Record.
+func (h *APILogHandler) Handle(ctx context.Context, r slog.Record) error {
+ // Convert slog level to API level
+ var apiLevel opencode.AppLogParamsLevel
+ switch r.Level {
+ case slog.LevelDebug, slog.LevelInfo:
+ apiLevel = opencode.AppLogParamsLevelInfo
+ case slog.LevelWarn:
+ apiLevel = opencode.AppLogParamsLevelWarn
+ case slog.LevelError:
+ apiLevel = opencode.AppLogParamsLevelError
+ default:
+ apiLevel = opencode.AppLogParamsLevelInfo
+ }
+
+ // Build extra fields
+ extra := make(map[string]any)
+
+ // Add handler attributes
+ h.mu.Lock()
+ for _, attr := range h.attrs {
+ extra[attr.Key] = attr.Value.Any()
+ }
+ h.mu.Unlock()
+
+ // Add record attributes
+ r.Attrs(func(attr slog.Attr) bool {
+ extra[attr.Key] = attr.Value.Any()
+ return true
+ })
+
+ // Send log to API
+ params := opencode.AppLogParams{
+ Service: opencode.F(h.service),
+ Level: opencode.F(apiLevel),
+ Message: opencode.F(r.Message),
+ }
+
+ if len(extra) > 0 {
+ params.Extra = opencode.F(extra)
+ }
+
+ // Use a goroutine to avoid blocking the logger
+ go func() {
+ _, err := h.client.App.Log(context.Background(), params)
+ if err != nil {
+ // Fallback: we can't log the error using slog as it would create a loop
+ // TODO: fallback file?
+ }
+ }()
+
+ return nil
+}
+
+// WithAttrs returns a new Handler whose attributes consist of
+// both the receiver's attributes and the arguments.
+func (h *APILogHandler) WithAttrs(attrs []slog.Attr) slog.Handler {
+ h.mu.Lock()
+ defer h.mu.Unlock()
+
+ newHandler := &APILogHandler{
+ client: h.client,
+ service: h.service,
+ level: h.level,
+ attrs: make([]slog.Attr, len(h.attrs)+len(attrs)),
+ groups: make([]string, len(h.groups)),
+ }
+
+ copy(newHandler.attrs, h.attrs)
+ copy(newHandler.attrs[len(h.attrs):], attrs)
+ copy(newHandler.groups, h.groups)
+
+ return newHandler
+}
+
+// WithGroup returns a new Handler with the given group appended to
+// the receiver's existing groups.
+func (h *APILogHandler) WithGroup(name string) slog.Handler {
+ h.mu.Lock()
+ defer h.mu.Unlock()
+
+ newHandler := &APILogHandler{
+ client: h.client,
+ service: h.service,
+ level: h.level,
+ attrs: make([]slog.Attr, len(h.attrs)),
+ groups: make([]string, len(h.groups)+1),
+ }
+
+ copy(newHandler.attrs, h.attrs)
+ copy(newHandler.groups, h.groups)
+ newHandler.groups[len(h.groups)] = name
+
+ return newHandler
+}
diff --git a/packages/tui/sdk/.stats.yml b/packages/tui/sdk/.stats.yml
index 4b404aded..d0927c6a6 100644
--- a/packages/tui/sdk/.stats.yml
+++ b/packages/tui/sdk/.stats.yml
@@ -1,4 +1,4 @@
-configured_endpoints: 20
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/opencode%2Fopencode-c06a9b8d8284683e8350fdd3eceff0b5756877f7b67e974acd565409b67d32a0.yml
-openapi_spec_hash: 5933bca0c79177065374ac724a6bc986
-config_hash: de53ecf98e1038f2cc2fd273b582f082
+configured_endpoints: 21
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/opencode%2Fopencode-3ae2247ea9674e156e5ad818e13d8cd8622737ee1b95fdcde23ebf50963df13c.yml
+openapi_spec_hash: 3075cca003eb61c035d3eb5891a6c38c
+config_hash: a2751b16a52007a1e12967ab4aa3729f
diff --git a/packages/tui/sdk/api.md b/packages/tui/sdk/api.md
index 967b8afe3..5a9077ad8 100644
--- a/packages/tui/sdk/api.md
+++ b/packages/tui/sdk/api.md
@@ -24,31 +24,32 @@ Methods:
- <code title="get /app">client.App.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#AppService.Get">Get</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>) (<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#App">App</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
- <code title="post /app/init">client.App.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#AppService.Init">Init</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>
+- <code title="post /log">client.App.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#AppService.Log">Log</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#AppLogParams">AppLogParams</a>) (<a href="https://pkg.go.dev/builtin#bool">bool</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
# Find
Response Types:
-- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#FindSymbolsResponse">FindSymbolsResponse</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#FindTextResponse">FindTextResponse</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#Match">Match</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#Symbol">Symbol</a>
Methods:
- <code title="get /find/file">client.Find.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#FindService.Files">Files</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, query <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#FindFilesParams">FindFilesParams</a>) ([]<a href="https://pkg.go.dev/builtin#string">string</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
-- <code title="get /find/symbol">client.Find.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#FindService.Symbols">Symbols</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, query <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#FindSymbolsParams">FindSymbolsParams</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#FindSymbolsResponse">FindSymbolsResponse</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
-- <code title="get /find">client.Find.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#FindService.Text">Text</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, query <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#FindTextParams">FindTextParams</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#FindTextResponse">FindTextResponse</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
+- <code title="get /find/symbol">client.Find.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#FindService.Symbols">Symbols</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, query <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#FindSymbolsParams">FindSymbolsParams</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#Symbol">Symbol</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
+- <code title="get /find">client.Find.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#FindService.Text">Text</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, query <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#FindTextParams">FindTextParams</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#Match">Match</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
# File
Response Types:
+- <a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#File">File</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#FileReadResponse">FileReadResponse</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#FileStatusResponse">FileStatusResponse</a>
Methods:
- <code title="get /file">client.File.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#FileService.Read">Read</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>, query <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#FileReadParams">FileReadParams</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#FileReadResponse">FileReadResponse</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
-- <code title="get /file/status">client.File.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#FileService.Status">Status</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>) ([]<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#FileStatusResponse">FileStatusResponse</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
+- <code title="get /file/status">client.File.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#FileService.Status">Status</a>(ctx <a href="https://pkg.go.dev/context">context</a>.<a href="https://pkg.go.dev/context#Context">Context</a>) ([]<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go">opencode</a>.<a href="https://pkg.go.dev/github.com/sst/opencode-sdk-go#File">File</a>, <a href="https://pkg.go.dev/builtin#error">error</a>)</code>
# Config
diff --git a/packages/tui/sdk/app.go b/packages/tui/sdk/app.go
index dc44a74b3..39ca3bd9e 100644
--- a/packages/tui/sdk/app.go
+++ b/packages/tui/sdk/app.go
@@ -7,6 +7,7 @@ import (
"net/http"
"github.com/sst/opencode-sdk-go/internal/apijson"
+ "github.com/sst/opencode-sdk-go/internal/param"
"github.com/sst/opencode-sdk-go/internal/requestconfig"
"github.com/sst/opencode-sdk-go/option"
)
@@ -46,6 +47,14 @@ func (r *AppService) Init(ctx context.Context, opts ...option.RequestOption) (re
return
}
+// Write a log entry to the server logs
+func (r *AppService) Log(ctx context.Context, body AppLogParams, opts ...option.RequestOption) (res *bool, err error) {
+ opts = append(r.Options[:], opts...)
+ path := "log"
+ err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, body, &res, opts...)
+ return
+}
+
type App struct {
Git bool `json:"git,required"`
Hostname string `json:"hostname,required"`
@@ -121,3 +130,35 @@ func (r *AppTime) UnmarshalJSON(data []byte) (err error) {
func (r appTimeJSON) RawJSON() string {
return r.raw
}
+
+type AppLogParams struct {
+ // Log level
+ Level param.Field[AppLogParamsLevel] `json:"level,required"`
+ // Log message
+ Message param.Field[string] `json:"message,required"`
+ // Service name for the log entry
+ Service param.Field[string] `json:"service,required"`
+ // Additional metadata for the log entry
+ Extra param.Field[map[string]interface{}] `json:"extra"`
+}
+
+func (r AppLogParams) MarshalJSON() (data []byte, err error) {
+ return apijson.MarshalRoot(r)
+}
+
+// Log level
+type AppLogParamsLevel string
+
+const (
+ AppLogParamsLevelInfo AppLogParamsLevel = "info"
+ AppLogParamsLevelError AppLogParamsLevel = "error"
+ AppLogParamsLevelWarn AppLogParamsLevel = "warn"
+)
+
+func (r AppLogParamsLevel) IsKnown() bool {
+ switch r {
+ case AppLogParamsLevelInfo, AppLogParamsLevelError, AppLogParamsLevelWarn:
+ return true
+ }
+ return false
+}
diff --git a/packages/tui/sdk/app_test.go b/packages/tui/sdk/app_test.go
index f96495f1c..5e7f58c71 100644
--- a/packages/tui/sdk/app_test.go
+++ b/packages/tui/sdk/app_test.go
@@ -56,3 +56,32 @@ func TestAppInit(t *testing.T) {
t.Fatalf("err should be nil: %s", err.Error())
}
}
+
+func TestAppLogWithOptionalParams(t *testing.T) {
+ t.Skip("skipped: tests are disabled for the time being")
+ baseURL := "http://localhost:4010"
+ if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok {
+ baseURL = envURL
+ }
+ if !testutil.CheckTestServer(t, baseURL) {
+ return
+ }
+ client := opencode.NewClient(
+ option.WithBaseURL(baseURL),
+ )
+ _, err := client.App.Log(context.TODO(), opencode.AppLogParams{
+ Level: opencode.F(opencode.AppLogParamsLevelInfo),
+ Message: opencode.F("message"),
+ Service: opencode.F("service"),
+ Extra: opencode.F(map[string]interface{}{
+ "foo": "bar",
+ }),
+ })
+ if err != nil {
+ var apierr *opencode.Error
+ if errors.As(err, &apierr) {
+ t.Log(string(apierr.DumpRequest(true)))
+ }
+ t.Fatalf("err should be nil: %s", err.Error())
+ }
+}
diff --git a/packages/tui/sdk/config.go b/packages/tui/sdk/config.go
index 503c17bd9..2f415c3fa 100644
--- a/packages/tui/sdk/config.go
+++ b/packages/tui/sdk/config.go
@@ -396,71 +396,71 @@ func (r configProviderModelsLimitJSON) RawJSON() string {
type Keybinds struct {
// Exit the application
- AppExit string `json:"app_exit"`
+ AppExit string `json:"app_exit,required"`
// Show help dialog
- AppHelp string `json:"app_help"`
+ AppHelp string `json:"app_help,required"`
// Open external editor
- EditorOpen string `json:"editor_open"`
+ EditorOpen string `json:"editor_open,required"`
// Close file
- FileClose string `json:"file_close"`
- // Toggle split/unified diff
- FileDiffToggle string `json:"file_diff_toggle"`
+ FileClose string `json:"file_close,required"`
+ // Split/unified diff
+ FileDiffToggle string `json:"file_diff_toggle,required"`
// List files
- FileList string `json:"file_list"`
+ FileList string `json:"file_list,required"`
// Search file
- FileSearch string `json:"file_search"`
+ FileSearch string `json:"file_search,required"`
// Clear input field
- InputClear string `json:"input_clear"`
+ InputClear string `json:"input_clear,required"`
// Insert newline in input
- InputNewline string `json:"input_newline"`
+ InputNewline string `json:"input_newline,required"`
// Paste from clipboard
- InputPaste string `json:"input_paste"`
+ InputPaste string `json:"input_paste,required"`
// Submit input
- InputSubmit string `json:"input_submit"`
+ InputSubmit string `json:"input_submit,required"`
// Leader key for keybind combinations
- Leader string `json:"leader"`
+ Leader string `json:"leader,required"`
// Copy message
- MessagesCopy string `json:"messages_copy"`
+ MessagesCopy string `json:"messages_copy,required"`
// Navigate to first message
- MessagesFirst string `json:"messages_first"`
+ MessagesFirst string `json:"messages_first,required"`
// Scroll messages down by half page
- MessagesHalfPageDown string `json:"messages_half_page_down"`
+ MessagesHalfPageDown string `json:"messages_half_page_down,required"`
// Scroll messages up by half page
- MessagesHalfPageUp string `json:"messages_half_page_up"`
+ MessagesHalfPageUp string `json:"messages_half_page_up,required"`
// Navigate to last message
- MessagesLast string `json:"messages_last"`
+ MessagesLast string `json:"messages_last,required"`
// Toggle layout
- MessagesLayoutToggle string `json:"messages_layout_toggle"`
+ MessagesLayoutToggle string `json:"messages_layout_toggle,required"`
// Navigate to next message
- MessagesNext string `json:"messages_next"`
+ MessagesNext string `json:"messages_next,required"`
// Scroll messages down by one page
- MessagesPageDown string `json:"messages_page_down"`
+ MessagesPageDown string `json:"messages_page_down,required"`
// Scroll messages up by one page
- MessagesPageUp string `json:"messages_page_up"`
+ MessagesPageUp string `json:"messages_page_up,required"`
// Navigate to previous message
- MessagesPrevious string `json:"messages_previous"`
+ MessagesPrevious string `json:"messages_previous,required"`
// Revert message
- MessagesRevert string `json:"messages_revert"`
+ MessagesRevert string `json:"messages_revert,required"`
// List available models
- ModelList string `json:"model_list"`
- // Initialize project configuration
- ProjectInit string `json:"project_init"`
- // Toggle compact mode for session
- SessionCompact string `json:"session_compact"`
+ ModelList string `json:"model_list,required"`
+ // Create/update AGENTS.md
+ ProjectInit string `json:"project_init,required"`
+ // Compact the session
+ SessionCompact string `json:"session_compact,required"`
// Interrupt current session
- SessionInterrupt string `json:"session_interrupt"`
+ SessionInterrupt string `json:"session_interrupt,required"`
// List all sessions
- SessionList string `json:"session_list"`
+ SessionList string `json:"session_list,required"`
// Create a new session
- SessionNew string `json:"session_new"`
+ SessionNew string `json:"session_new,required"`
// Share current session
- SessionShare string `json:"session_share"`
+ SessionShare string `json:"session_share,required"`
// Unshare current session
- SessionUnshare string `json:"session_unshare"`
+ SessionUnshare string `json:"session_unshare,required"`
// List available themes
- ThemeList string `json:"theme_list"`
- // Show tool details
- ToolDetails string `json:"tool_details"`
+ ThemeList string `json:"theme_list,required"`
+ // Toggle tool details
+ ToolDetails string `json:"tool_details,required"`
JSON keybindsJSON `json:"-"`
}
diff --git a/packages/tui/sdk/event.go b/packages/tui/sdk/event.go
index 89da8a078..8bbf636c3 100644
--- a/packages/tui/sdk/event.go
+++ b/packages/tui/sdk/event.go
@@ -916,14 +916,16 @@ func (r eventListResponseEventSessionErrorJSON) RawJSON() string {
func (r EventListResponseEventSessionError) implementsEventListResponse() {}
type EventListResponseEventSessionErrorProperties struct {
- Error EventListResponseEventSessionErrorPropertiesError `json:"error"`
- JSON eventListResponseEventSessionErrorPropertiesJSON `json:"-"`
+ Error EventListResponseEventSessionErrorPropertiesError `json:"error"`
+ SessionID string `json:"sessionID"`
+ JSON eventListResponseEventSessionErrorPropertiesJSON `json:"-"`
}
// eventListResponseEventSessionErrorPropertiesJSON contains the JSON metadata for
// the struct [EventListResponseEventSessionErrorProperties]
type eventListResponseEventSessionErrorPropertiesJSON struct {
Error apijson.Field
+ SessionID apijson.Field
raw string
ExtraFields map[string]apijson.Field
}
diff --git a/packages/tui/sdk/file.go b/packages/tui/sdk/file.go
index a9d6f018c..0a8a4b2b6 100644
--- a/packages/tui/sdk/file.go
+++ b/packages/tui/sdk/file.go
@@ -42,89 +42,88 @@ func (r *FileService) Read(ctx context.Context, query FileReadParams, opts ...op
}
// Get file status
-func (r *FileService) Status(ctx context.Context, opts ...option.RequestOption) (res *[]FileStatusResponse, err error) {
+func (r *FileService) Status(ctx context.Context, opts ...option.RequestOption) (res *[]File, err error) {
opts = append(r.Options[:], opts...)
path := "file/status"
err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, nil, &res, opts...)
return
}
-type FileReadResponse struct {
- Content string `json:"content,required"`
- Type FileReadResponseType `json:"type,required"`
- JSON fileReadResponseJSON `json:"-"`
+type File struct {
+ Added int64 `json:"added,required"`
+ Path string `json:"path,required"`
+ Removed int64 `json:"removed,required"`
+ Status FileStatus `json:"status,required"`
+ JSON fileJSON `json:"-"`
}
-// fileReadResponseJSON contains the JSON metadata for the struct
-// [FileReadResponse]
-type fileReadResponseJSON struct {
- Content apijson.Field
- Type apijson.Field
+// fileJSON contains the JSON metadata for the struct [File]
+type fileJSON struct {
+ Added apijson.Field
+ Path apijson.Field
+ Removed apijson.Field
+ Status apijson.Field
raw string
ExtraFields map[string]apijson.Field
}
-func (r *FileReadResponse) UnmarshalJSON(data []byte) (err error) {
+func (r *File) UnmarshalJSON(data []byte) (err error) {
return apijson.UnmarshalRoot(data, r)
}
-func (r fileReadResponseJSON) RawJSON() string {
+func (r fileJSON) RawJSON() string {
return r.raw
}
-type FileReadResponseType string
+type FileStatus string
const (
- FileReadResponseTypeRaw FileReadResponseType = "raw"
- FileReadResponseTypePatch FileReadResponseType = "patch"
+ FileStatusAdded FileStatus = "added"
+ FileStatusDeleted FileStatus = "deleted"
+ FileStatusModified FileStatus = "modified"
)
-func (r FileReadResponseType) IsKnown() bool {
+func (r FileStatus) IsKnown() bool {
switch r {
- case FileReadResponseTypeRaw, FileReadResponseTypePatch:
+ case FileStatusAdded, FileStatusDeleted, FileStatusModified:
return true
}
return false
}
-type FileStatusResponse struct {
- Added int64 `json:"added,required"`
- File string `json:"file,required"`
- Removed int64 `json:"removed,required"`
- Status FileStatusResponseStatus `json:"status,required"`
- JSON fileStatusResponseJSON `json:"-"`
+type FileReadResponse struct {
+ Content string `json:"content,required"`
+ Type FileReadResponseType `json:"type,required"`
+ JSON fileReadResponseJSON `json:"-"`
}
-// fileStatusResponseJSON contains the JSON metadata for the struct
-// [FileStatusResponse]
-type fileStatusResponseJSON struct {
- Added apijson.Field
- File apijson.Field
- Removed apijson.Field
- Status apijson.Field
+// fileReadResponseJSON contains the JSON metadata for the struct
+// [FileReadResponse]
+type fileReadResponseJSON struct {
+ Content apijson.Field
+ Type apijson.Field
raw string
ExtraFields map[string]apijson.Field
}
-func (r *FileStatusResponse) UnmarshalJSON(data []byte) (err error) {
+func (r *FileReadResponse) UnmarshalJSON(data []byte) (err error) {
return apijson.UnmarshalRoot(data, r)
}
-func (r fileStatusResponseJSON) RawJSON() string {
+func (r fileReadResponseJSON) RawJSON() string {
return r.raw
}
-type FileStatusResponseStatus string
+type FileReadResponseType string
const (
- FileStatusResponseStatusAdded FileStatusResponseStatus = "added"
- FileStatusResponseStatusDeleted FileStatusResponseStatus = "deleted"
- FileStatusResponseStatusModified FileStatusResponseStatus = "modified"
+ FileReadResponseTypeRaw FileReadResponseType = "raw"
+ FileReadResponseTypePatch FileReadResponseType = "patch"
)
-func (r FileStatusResponseStatus) IsKnown() bool {
+func (r FileReadResponseType) IsKnown() bool {
switch r {
- case FileStatusResponseStatusAdded, FileStatusResponseStatusDeleted, FileStatusResponseStatusModified:
+ case FileReadResponseTypeRaw, FileReadResponseTypePatch:
return true
}
return false
diff --git a/packages/tui/sdk/find.go b/packages/tui/sdk/find.go
index bbd6b680b..10f92fc05 100644
--- a/packages/tui/sdk/find.go
+++ b/packages/tui/sdk/find.go
@@ -42,7 +42,7 @@ func (r *FindService) Files(ctx context.Context, query FindFilesParams, opts ...
}
// Find workspace symbols
-func (r *FindService) Symbols(ctx context.Context, query FindSymbolsParams, opts ...option.RequestOption) (res *[]FindSymbolsResponse, err error) {
+func (r *FindService) Symbols(ctx context.Context, query FindSymbolsParams, opts ...option.RequestOption) (res *[]Symbol, err error) {
opts = append(r.Options[:], opts...)
path := "find/symbol"
err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, query, &res, opts...)
@@ -50,27 +50,24 @@ func (r *FindService) Symbols(ctx context.Context, query FindSymbolsParams, opts
}
// Find text in files
-func (r *FindService) Text(ctx context.Context, query FindTextParams, opts ...option.RequestOption) (res *[]FindTextResponse, err error) {
+func (r *FindService) Text(ctx context.Context, query FindTextParams, opts ...option.RequestOption) (res *[]Match, err error) {
opts = append(r.Options[:], opts...)
path := "find"
err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, query, &res, opts...)
return
}
-type FindSymbolsResponse = interface{}
-
-type FindTextResponse struct {
- AbsoluteOffset float64 `json:"absolute_offset,required"`
- LineNumber float64 `json:"line_number,required"`
- Lines FindTextResponseLines `json:"lines,required"`
- Path FindTextResponsePath `json:"path,required"`
- Submatches []FindTextResponseSubmatch `json:"submatches,required"`
- JSON findTextResponseJSON `json:"-"`
+type Match struct {
+ AbsoluteOffset float64 `json:"absolute_offset,required"`
+ LineNumber float64 `json:"line_number,required"`
+ Lines MatchLines `json:"lines,required"`
+ Path MatchPath `json:"path,required"`
+ Submatches []MatchSubmatch `json:"submatches,required"`
+ JSON matchJSON `json:"-"`
}
-// findTextResponseJSON contains the JSON metadata for the struct
-// [FindTextResponse]
-type findTextResponseJSON struct {
+// matchJSON contains the JSON metadata for the struct [Match]
+type matchJSON struct {
AbsoluteOffset apijson.Field
LineNumber apijson.Field
Lines apijson.Field
@@ -80,66 +77,63 @@ type findTextResponseJSON struct {
ExtraFields map[string]apijson.Field
}
-func (r *FindTextResponse) UnmarshalJSON(data []byte) (err error) {
+func (r *Match) UnmarshalJSON(data []byte) (err error) {
return apijson.UnmarshalRoot(data, r)
}
-func (r findTextResponseJSON) RawJSON() string {
+func (r matchJSON) RawJSON() string {
return r.raw
}
-type FindTextResponseLines struct {
- Text string `json:"text,required"`
- JSON findTextResponseLinesJSON `json:"-"`
+type MatchLines struct {
+ Text string `json:"text,required"`
+ JSON matchLinesJSON `json:"-"`
}
-// findTextResponseLinesJSON contains the JSON metadata for the struct
-// [FindTextResponseLines]
-type findTextResponseLinesJSON struct {
+// matchLinesJSON contains the JSON metadata for the struct [MatchLines]
+type matchLinesJSON struct {
Text apijson.Field
raw string
ExtraFields map[string]apijson.Field
}
-func (r *FindTextResponseLines) UnmarshalJSON(data []byte) (err error) {
+func (r *MatchLines) UnmarshalJSON(data []byte) (err error) {
return apijson.UnmarshalRoot(data, r)
}
-func (r findTextResponseLinesJSON) RawJSON() string {
+func (r matchLinesJSON) RawJSON() string {
return r.raw
}
-type FindTextResponsePath struct {
- Text string `json:"text,required"`
- JSON findTextResponsePathJSON `json:"-"`
+type MatchPath struct {
+ Text string `json:"text,required"`
+ JSON matchPathJSON `json:"-"`
}
-// findTextResponsePathJSON contains the JSON metadata for the struct
-// [FindTextResponsePath]
-type findTextResponsePathJSON struct {
+// matchPathJSON contains the JSON metadata for the struct [MatchPath]
+type matchPathJSON struct {
Text apijson.Field
raw string
ExtraFields map[string]apijson.Field
}
-func (r *FindTextResponsePath) UnmarshalJSON(data []byte) (err error) {
+func (r *MatchPath) UnmarshalJSON(data []byte) (err error) {
return apijson.UnmarshalRoot(data, r)
}
-func (r findTextResponsePathJSON) RawJSON() string {
+func (r matchPathJSON) RawJSON() string {
return r.raw
}
-type FindTextResponseSubmatch struct {
- End float64 `json:"end,required"`
- Match FindTextResponseSubmatchesMatch `json:"match,required"`
- Start float64 `json:"start,required"`
- JSON findTextResponseSubmatchJSON `json:"-"`
+type MatchSubmatch struct {
+ End float64 `json:"end,required"`
+ Match MatchSubmatchesMatch `json:"match,required"`
+ Start float64 `json:"start,required"`
+ JSON matchSubmatchJSON `json:"-"`
}
-// findTextResponseSubmatchJSON contains the JSON metadata for the struct
-// [FindTextResponseSubmatch]
-type findTextResponseSubmatchJSON struct {
+// matchSubmatchJSON contains the JSON metadata for the struct [MatchSubmatch]
+type matchSubmatchJSON struct {
End apijson.Field
Match apijson.Field
Start apijson.Field
@@ -147,32 +141,147 @@ type findTextResponseSubmatchJSON struct {
ExtraFields map[string]apijson.Field
}
-func (r *FindTextResponseSubmatch) UnmarshalJSON(data []byte) (err error) {
+func (r *MatchSubmatch) UnmarshalJSON(data []byte) (err error) {
return apijson.UnmarshalRoot(data, r)
}
-func (r findTextResponseSubmatchJSON) RawJSON() string {
+func (r matchSubmatchJSON) RawJSON() string {
return r.raw
}
-type FindTextResponseSubmatchesMatch struct {
- Text string `json:"text,required"`
- JSON findTextResponseSubmatchesMatchJSON `json:"-"`
+type MatchSubmatchesMatch struct {
+ Text string `json:"text,required"`
+ JSON matchSubmatchesMatchJSON `json:"-"`
}
-// findTextResponseSubmatchesMatchJSON contains the JSON metadata for the struct
-// [FindTextResponseSubmatchesMatch]
-type findTextResponseSubmatchesMatchJSON struct {
+// matchSubmatchesMatchJSON contains the JSON metadata for the struct
+// [MatchSubmatchesMatch]
+type matchSubmatchesMatchJSON struct {
Text apijson.Field
raw string
ExtraFields map[string]apijson.Field
}
-func (r *FindTextResponseSubmatchesMatch) UnmarshalJSON(data []byte) (err error) {
+func (r *MatchSubmatchesMatch) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r matchSubmatchesMatchJSON) RawJSON() string {
+ return r.raw
+}
+
+type Symbol struct {
+ Kind float64 `json:"kind,required"`
+ Location SymbolLocation `json:"location,required"`
+ Name string `json:"name,required"`
+ JSON symbolJSON `json:"-"`
+}
+
+// symbolJSON contains the JSON metadata for the struct [Symbol]
+type symbolJSON struct {
+ Kind apijson.Field
+ Location apijson.Field
+ Name apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *Symbol) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r symbolJSON) RawJSON() string {
+ return r.raw
+}
+
+type SymbolLocation struct {
+ Range SymbolLocationRange `json:"range,required"`
+ Uri string `json:"uri,required"`
+ JSON symbolLocationJSON `json:"-"`
+}
+
+// symbolLocationJSON contains the JSON metadata for the struct [SymbolLocation]
+type symbolLocationJSON struct {
+ Range apijson.Field
+ Uri apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *SymbolLocation) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r symbolLocationJSON) RawJSON() string {
+ return r.raw
+}
+
+type SymbolLocationRange struct {
+ End SymbolLocationRangeEnd `json:"end,required"`
+ Start SymbolLocationRangeStart `json:"start,required"`
+ JSON symbolLocationRangeJSON `json:"-"`
+}
+
+// symbolLocationRangeJSON contains the JSON metadata for the struct
+// [SymbolLocationRange]
+type symbolLocationRangeJSON struct {
+ End apijson.Field
+ Start apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *SymbolLocationRange) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r symbolLocationRangeJSON) RawJSON() string {
+ return r.raw
+}
+
+type SymbolLocationRangeEnd struct {
+ Character float64 `json:"character,required"`
+ Line float64 `json:"line,required"`
+ JSON symbolLocationRangeEndJSON `json:"-"`
+}
+
+// symbolLocationRangeEndJSON contains the JSON metadata for the struct
+// [SymbolLocationRangeEnd]
+type symbolLocationRangeEndJSON struct {
+ Character apijson.Field
+ Line apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *SymbolLocationRangeEnd) UnmarshalJSON(data []byte) (err error) {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func (r symbolLocationRangeEndJSON) RawJSON() string {
+ return r.raw
+}
+
+type SymbolLocationRangeStart struct {
+ Character float64 `json:"character,required"`
+ Line float64 `json:"line,required"`
+ JSON symbolLocationRangeStartJSON `json:"-"`
+}
+
+// symbolLocationRangeStartJSON contains the JSON metadata for the struct
+// [SymbolLocationRangeStart]
+type symbolLocationRangeStartJSON struct {
+ Character apijson.Field
+ Line apijson.Field
+ raw string
+ ExtraFields map[string]apijson.Field
+}
+
+func (r *SymbolLocationRangeStart) UnmarshalJSON(data []byte) (err error) {
return apijson.UnmarshalRoot(data, r)
}
-func (r findTextResponseSubmatchesMatchJSON) RawJSON() string {
+func (r symbolLocationRangeStartJSON) RawJSON() string {
return r.raw
}
diff --git a/packages/tui/sdk/packages/ssestream/ssestream.go b/packages/tui/sdk/packages/ssestream/ssestream.go
index 87ab56f2c..cc0afb7b1 100644
--- a/packages/tui/sdk/packages/ssestream/ssestream.go
+++ b/packages/tui/sdk/packages/ssestream/ssestream.go
@@ -29,7 +29,7 @@ func NewDecoder(res *http.Response) Decoder {
decoder = t(res.Body)
} else {
scn := bufio.NewScanner(res.Body)
- scn.Buffer(nil, (bufio.MaxScanTokenSize<<4)*10)
+ scn.Buffer(nil, bufio.MaxScanTokenSize<<9)
decoder = &eventStreamDecoder{rc: res.Body, scn: scn}
}
return decoder
diff --git a/packages/tui/sdk/scripts/lint b/packages/tui/sdk/scripts/lint
index c10fa02f6..9f37abf28 100755
--- a/packages/tui/sdk/scripts/lint
+++ b/packages/tui/sdk/scripts/lint
@@ -7,5 +7,5 @@ cd "$(dirname "$0")/.."
echo "==> Running Go build"
go build .
-# Compile the tests but don't run them
-go test -c .
+echo "==> Checking tests compile"
+go test -run=^$ .
diff --git a/stainless.yml b/stainless.yml
index 2e262b749..91f8043fc 100644
--- a/stainless.yml
+++ b/stainless.yml
@@ -51,14 +51,20 @@ resources:
methods:
get: get /app
init: post /app/init
+ log: post /log
find:
+ models:
+ match: Match
+ symbol: Symbol
methods:
text: get /find
files: get /find/file
symbols: get /find/symbol
file:
+ models:
+ file: File
methods:
read: get /file
status: get /file/status