mirror of
https://github.com/anomalyco/opencode.git
synced 2026-08-10 03:19:59 -04:00
Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 4e4cff49c0 | |||
| 5540503bee | |||
| 193718034b | |||
| 72108c0296 | |||
| ec1c9f8cd1 | |||
| a85b0a370e | |||
| e7784d2864 |
@@ -4,6 +4,7 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- dev
|
||||
- production
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency: ${{ github.workflow }}-${{ github.ref }}
|
||||
@@ -20,6 +21,6 @@ jobs:
|
||||
|
||||
- run: bun install
|
||||
|
||||
- run: bun sst deploy --stage=dev
|
||||
- run: bun sst deploy --stage=${{ github.ref_name }}
|
||||
env:
|
||||
CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"keybinds": {},
|
||||
"mcp": {}
|
||||
}
|
||||
|
||||
@@ -120,7 +120,7 @@ export default {
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
secret,
|
||||
url: "https://dev.opencode.ai/s/" + short,
|
||||
url: "https://opencode.ai/s/" + short,
|
||||
}),
|
||||
{
|
||||
headers: { "Content-Type": "application/json" },
|
||||
|
||||
@@ -2,97 +2,127 @@
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"$schema": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"description": "JSON schema reference for configuration validation"
|
||||
},
|
||||
"theme": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"description": "Theme name to use for the interface"
|
||||
},
|
||||
"keybinds": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"leader": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"description": "Leader key for keybind combinations"
|
||||
},
|
||||
"help": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"description": "Show help dialog"
|
||||
},
|
||||
"editor_open": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"description": "Open external editor"
|
||||
},
|
||||
"session_new": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"description": "Create a new session"
|
||||
},
|
||||
"session_list": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"description": "List all sessions"
|
||||
},
|
||||
"session_share": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"description": "Share current session"
|
||||
},
|
||||
"session_interrupt": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"description": "Interrupt current session"
|
||||
},
|
||||
"session_compact": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"description": "Toggle compact mode for session"
|
||||
},
|
||||
"tool_details": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"description": "Show tool details"
|
||||
},
|
||||
"model_list": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"description": "List available models"
|
||||
},
|
||||
"theme_list": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"description": "List available themes"
|
||||
},
|
||||
"project_init": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"description": "Initialize project configuration"
|
||||
},
|
||||
"input_clear": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"description": "Clear input field"
|
||||
},
|
||||
"input_paste": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"description": "Paste from clipboard"
|
||||
},
|
||||
"input_submit": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"description": "Submit input"
|
||||
},
|
||||
"input_newline": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"description": "Insert newline in input"
|
||||
},
|
||||
"history_previous": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"description": "Navigate to previous history item"
|
||||
},
|
||||
"history_next": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"description": "Navigate to next history item"
|
||||
},
|
||||
"messages_page_up": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"description": "Scroll messages up by one page"
|
||||
},
|
||||
"messages_page_down": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"description": "Scroll messages down by one page"
|
||||
},
|
||||
"messages_half_page_up": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"description": "Scroll messages up by half page"
|
||||
},
|
||||
"messages_half_page_down": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"description": "Scroll messages down by half page"
|
||||
},
|
||||
"messages_previous": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"description": "Navigate to previous message"
|
||||
},
|
||||
"messages_next": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"description": "Navigate to next message"
|
||||
},
|
||||
"messages_first": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"description": "Navigate to first message"
|
||||
},
|
||||
"messages_last": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"description": "Navigate to last message"
|
||||
},
|
||||
"app_exit": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"description": "Exit the application"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
"additionalProperties": false,
|
||||
"description": "Custom keybind configurations"
|
||||
},
|
||||
"autoshare": {
|
||||
"type": "boolean",
|
||||
@@ -207,7 +237,8 @@
|
||||
"models"
|
||||
],
|
||||
"additionalProperties": false
|
||||
}
|
||||
},
|
||||
"description": "Custom provider configurations and model overrides"
|
||||
},
|
||||
"mcp": {
|
||||
"type": "object",
|
||||
@@ -218,19 +249,22 @@
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"const": "local"
|
||||
"const": "local",
|
||||
"description": "Type of MCP server connection"
|
||||
},
|
||||
"command": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"description": "Command and arguments to run the MCP server"
|
||||
},
|
||||
"environment": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"description": "Environment variables to set when running the MCP server"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -244,10 +278,12 @@
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"const": "remote"
|
||||
"const": "remote",
|
||||
"description": "Type of MCP server connection"
|
||||
},
|
||||
"url": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"description": "URL of the remote MCP server"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -257,7 +293,8 @@
|
||||
"additionalProperties": false
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"description": "MCP (Model Context Protocol) server configurations"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
|
||||
@@ -80,9 +80,9 @@ function main() {
|
||||
|
||||
// Create symlink to the actual binary
|
||||
fs.symlinkSync(binaryPath, binScript)
|
||||
console.log(`OpenCode binary symlinked: ${binScript} -> ${binaryPath}`)
|
||||
console.log(`opencode binary symlinked: ${binScript} -> ${binaryPath}`)
|
||||
} catch (error) {
|
||||
console.error("Failed to create OpenCode binary symlink:", error.message)
|
||||
console.error("Failed to create opencode binary symlink:", error.message)
|
||||
process.exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,11 +20,12 @@ const TOOL: Record<string, [string, string]> = {
|
||||
list: ["List", UI.Style.TEXT_INFO_BOLD],
|
||||
read: ["Read", UI.Style.TEXT_HIGHLIGHT_BOLD],
|
||||
write: ["Write", UI.Style.TEXT_SUCCESS_BOLD],
|
||||
websearch: ["Search", UI.Style.TEXT_DIM_BOLD],
|
||||
}
|
||||
|
||||
export const RunCommand = cmd({
|
||||
command: "run [message..]",
|
||||
describe: "Run OpenCode with a message",
|
||||
describe: "Run opencode with a message",
|
||||
builder: (yargs: Argv) => {
|
||||
return yargs
|
||||
.positional("message", {
|
||||
@@ -89,7 +90,7 @@ export const RunCommand = cmd({
|
||||
await Session.share(session.id)
|
||||
UI.println(
|
||||
UI.Style.TEXT_INFO_BOLD +
|
||||
"~ https://dev.opencode.ai/s/" +
|
||||
"~ https://opencode.ai/s/" +
|
||||
session.id.slice(-8),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -44,9 +44,9 @@ export namespace Config {
|
||||
|
||||
export const McpLocal = z
|
||||
.object({
|
||||
type: z.literal("local"),
|
||||
command: z.string().array(),
|
||||
environment: z.record(z.string(), z.string()).optional(),
|
||||
type: z.literal("local").describe("Type of MCP server connection"),
|
||||
command: z.string().array().describe("Command and arguments to run the MCP server"),
|
||||
environment: z.record(z.string(), z.string()).optional().describe("Environment variables to set when running the MCP server"),
|
||||
})
|
||||
.openapi({
|
||||
ref: "Config.McpLocal",
|
||||
@@ -54,8 +54,8 @@ export namespace Config {
|
||||
|
||||
export const McpRemote = z
|
||||
.object({
|
||||
type: z.literal("remote"),
|
||||
url: z.string(),
|
||||
type: z.literal("remote").describe("Type of MCP server connection"),
|
||||
url: z.string().describe("URL of the remote MCP server"),
|
||||
})
|
||||
.openapi({
|
||||
ref: "Config.McpRemote",
|
||||
@@ -66,42 +66,42 @@ export namespace Config {
|
||||
|
||||
export const Keybinds = z
|
||||
.object({
|
||||
leader: z.string().optional(),
|
||||
help: z.string().optional(),
|
||||
editor_open: z.string().optional(),
|
||||
session_new: z.string().optional(),
|
||||
session_list: z.string().optional(),
|
||||
session_share: z.string().optional(),
|
||||
session_interrupt: z.string().optional(),
|
||||
session_compact: z.string().optional(),
|
||||
tool_details: z.string().optional(),
|
||||
model_list: z.string().optional(),
|
||||
theme_list: z.string().optional(),
|
||||
project_init: z.string().optional(),
|
||||
input_clear: z.string().optional(),
|
||||
input_paste: z.string().optional(),
|
||||
input_submit: z.string().optional(),
|
||||
input_newline: z.string().optional(),
|
||||
history_previous: z.string().optional(),
|
||||
history_next: z.string().optional(),
|
||||
messages_page_up: z.string().optional(),
|
||||
messages_page_down: z.string().optional(),
|
||||
messages_half_page_up: z.string().optional(),
|
||||
messages_half_page_down: z.string().optional(),
|
||||
messages_previous: z.string().optional(),
|
||||
messages_next: z.string().optional(),
|
||||
messages_first: z.string().optional(),
|
||||
messages_last: z.string().optional(),
|
||||
app_exit: z.string().optional(),
|
||||
leader: z.string().optional().describe("Leader key for keybind combinations"),
|
||||
help: z.string().optional().describe("Show help dialog"),
|
||||
editor_open: z.string().optional().describe("Open external editor"),
|
||||
session_new: z.string().optional().describe("Create a new session"),
|
||||
session_list: z.string().optional().describe("List all sessions"),
|
||||
session_share: z.string().optional().describe("Share current session"),
|
||||
session_interrupt: z.string().optional().describe("Interrupt current session"),
|
||||
session_compact: z.string().optional().describe("Toggle compact mode for session"),
|
||||
tool_details: z.string().optional().describe("Show tool details"),
|
||||
model_list: z.string().optional().describe("List available models"),
|
||||
theme_list: z.string().optional().describe("List available themes"),
|
||||
project_init: z.string().optional().describe("Initialize project configuration"),
|
||||
input_clear: z.string().optional().describe("Clear input field"),
|
||||
input_paste: z.string().optional().describe("Paste from clipboard"),
|
||||
input_submit: z.string().optional().describe("Submit input"),
|
||||
input_newline: z.string().optional().describe("Insert newline in input"),
|
||||
history_previous: z.string().optional().describe("Navigate to previous history item"),
|
||||
history_next: z.string().optional().describe("Navigate to next history item"),
|
||||
messages_page_up: z.string().optional().describe("Scroll messages up by one page"),
|
||||
messages_page_down: z.string().optional().describe("Scroll messages down by one page"),
|
||||
messages_half_page_up: z.string().optional().describe("Scroll messages up by half page"),
|
||||
messages_half_page_down: z.string().optional().describe("Scroll messages down by half page"),
|
||||
messages_previous: z.string().optional().describe("Navigate to previous message"),
|
||||
messages_next: z.string().optional().describe("Navigate to next message"),
|
||||
messages_first: z.string().optional().describe("Navigate to first message"),
|
||||
messages_last: z.string().optional().describe("Navigate to last message"),
|
||||
app_exit: z.string().optional().describe("Exit the application"),
|
||||
})
|
||||
.openapi({
|
||||
ref: "Config.Keybinds",
|
||||
})
|
||||
export const Info = z
|
||||
.object({
|
||||
$schema: z.string().optional(),
|
||||
theme: z.string().optional(),
|
||||
keybinds: Keybinds.optional(),
|
||||
$schema: z.string().optional().describe("JSON schema reference for configuration validation"),
|
||||
theme: z.string().optional().describe("Theme name to use for the interface"),
|
||||
keybinds: Keybinds.optional().describe("Custom keybind configurations"),
|
||||
autoshare: z
|
||||
.boolean()
|
||||
.optional()
|
||||
@@ -127,8 +127,9 @@ export namespace Config {
|
||||
options: z.record(z.any()).optional(),
|
||||
}),
|
||||
)
|
||||
.optional(),
|
||||
mcp: z.record(z.string(), Mcp).optional(),
|
||||
.optional()
|
||||
.describe("Custom provider configurations and model overrides"),
|
||||
mcp: z.record(z.string(), Mcp).optional().describe("MCP (Model Context Protocol) server configurations"),
|
||||
})
|
||||
.openapi({
|
||||
ref: "Config.Info",
|
||||
|
||||
@@ -41,6 +41,10 @@ export namespace Installation {
|
||||
return VERSION.startsWith("0.0.0")
|
||||
}
|
||||
|
||||
export function isDev() {
|
||||
return VERSION === "dev"
|
||||
}
|
||||
|
||||
export async function method() {
|
||||
if (process.execPath.includes(path.join(".opencode", "bin"))) return "curl"
|
||||
const exec = process.execPath.toLowerCase()
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { App } from "../app/app"
|
||||
import { Bus } from "../bus"
|
||||
import { Installation } from "../installation"
|
||||
import { Session } from "../session"
|
||||
import { Storage } from "../storage/storage"
|
||||
import { Log } from "../util/log"
|
||||
@@ -56,7 +57,10 @@ export namespace Share {
|
||||
}
|
||||
|
||||
export const URL =
|
||||
process.env["OPENCODE_API"] ?? "https://api.dev.opencode.ai"
|
||||
process.env["OPENCODE_API"] ??
|
||||
(Installation.isSnapshot() || Installation.isDev()
|
||||
? "https://api.dev.opencode.ai"
|
||||
: "https://api.opencode.ai")
|
||||
|
||||
export async function create(sessionID: string) {
|
||||
return fetch(`${URL}/share_create`, {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
- Allows OpenCode to search the web and use the results to inform responses
|
||||
- Allows opencode to search the web and use the results to inform responses
|
||||
- Provides up-to-date information for current events and recent data
|
||||
- Returns search result information formatted as search result blocks
|
||||
- Use this tool for accessing information beyond Claude's knowledge cutoff
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package chat
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"slices"
|
||||
@@ -252,6 +253,7 @@ func renderToolInvocation(
|
||||
metadata client.MessageInfo_Metadata_Tool_AdditionalProperties,
|
||||
showDetails bool,
|
||||
isLast bool,
|
||||
contentOnly bool,
|
||||
) string {
|
||||
ignoredTools := []string{"todoread"}
|
||||
if slices.Contains(ignoredTools, toolCall.ToolName) {
|
||||
@@ -305,14 +307,19 @@ func renderToolInvocation(
|
||||
toolArgsMap := make(map[string]any)
|
||||
if toolCall.Args != nil {
|
||||
value := *toolCall.Args
|
||||
m, ok := value.(map[string]any)
|
||||
if ok {
|
||||
if m, ok := value.(map[string]any); ok {
|
||||
toolArgsMap = m
|
||||
firstKey := ""
|
||||
|
||||
keys := make([]string, 0, len(toolArgsMap))
|
||||
for key := range toolArgsMap {
|
||||
firstKey = key
|
||||
break
|
||||
keys = append(keys, key)
|
||||
}
|
||||
slices.Sort(keys)
|
||||
firstKey := ""
|
||||
if len(keys) > 0 {
|
||||
firstKey = keys[0]
|
||||
}
|
||||
|
||||
toolArgs = renderArgs(&toolArgsMap, firstKey)
|
||||
}
|
||||
}
|
||||
@@ -448,14 +455,60 @@ func renderToolInvocation(
|
||||
body = toMarkdown(body, innerWidth, t.BackgroundSubtle())
|
||||
body = renderContentBlock(body, WithFullWidth(), WithMarginBottom(1))
|
||||
}
|
||||
case "task":
|
||||
if description, ok := toolArgsMap["description"].(string); ok {
|
||||
title = fmt.Sprintf("TASK %s %s", description, elapsed)
|
||||
if summary, ok := metadata.Get("summary"); ok {
|
||||
toolcalls := summary.([]any)
|
||||
// toolcalls :=
|
||||
|
||||
steps := []string{}
|
||||
for _, toolcall := range toolcalls {
|
||||
call := toolcall.(map[string]any)
|
||||
if toolInvocation, ok := call["toolInvocation"].(map[string]any); ok {
|
||||
data, _ := json.Marshal(toolInvocation)
|
||||
var toolCall client.MessageToolInvocationToolCall
|
||||
_ = json.Unmarshal(data, &toolCall)
|
||||
|
||||
if metadata, ok := call["metadata"].(map[string]any); ok {
|
||||
data, _ = json.Marshal(metadata)
|
||||
var toolMetadata client.MessageInfo_Metadata_Tool_AdditionalProperties
|
||||
_ = json.Unmarshal(data, &toolMetadata)
|
||||
|
||||
step := renderToolInvocation(
|
||||
toolCall,
|
||||
nil,
|
||||
toolMetadata,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
)
|
||||
steps = append(steps, step)
|
||||
}
|
||||
}
|
||||
}
|
||||
body = strings.Join(steps, "\n")
|
||||
body = renderContentBlock(body, WithFullWidth(), WithMarginBottom(1))
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
toolName := renderToolName(toolCall.ToolName)
|
||||
title = fmt.Sprintf("%s %s %s", toolName, toolArgs, elapsed)
|
||||
if result == nil {
|
||||
empty := ""
|
||||
result = &empty
|
||||
}
|
||||
body = *result
|
||||
body = truncateHeight(body, 10)
|
||||
body = renderContentBlock(body, WithFullWidth(), WithMarginBottom(1))
|
||||
}
|
||||
|
||||
if contentOnly {
|
||||
title = "∟ " + title
|
||||
return title
|
||||
}
|
||||
|
||||
if !showDetails {
|
||||
title = "∟ " + title
|
||||
padding := calculatePadding()
|
||||
@@ -496,8 +549,6 @@ func renderToolInvocation(
|
||||
|
||||
func renderToolName(name string) string {
|
||||
switch name {
|
||||
// case agent.AgentToolName:
|
||||
// return "Task"
|
||||
case "list":
|
||||
return "LIST"
|
||||
case "webfetch":
|
||||
@@ -557,8 +608,8 @@ func renderFile(filename string, content string, options ...fileRenderingOption)
|
||||
|
||||
func renderToolAction(name string) string {
|
||||
switch name {
|
||||
// case agent.AgentToolName:
|
||||
// return "Preparing prompt..."
|
||||
case "task":
|
||||
return "Searching..."
|
||||
case "bash":
|
||||
return "Building command..."
|
||||
case "edit":
|
||||
@@ -589,9 +640,17 @@ func renderArgs(args *map[string]any, titleKey string) string {
|
||||
if args == nil || len(*args) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
keys := make([]string, 0, len(*args))
|
||||
for key := range *args {
|
||||
keys = append(keys, key)
|
||||
}
|
||||
slices.Sort(keys)
|
||||
|
||||
title := ""
|
||||
parts := []string{}
|
||||
for key, value := range *args {
|
||||
for _, key := range keys {
|
||||
value := (*args)[key]
|
||||
if value == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -191,6 +191,7 @@ func (m *messagesComponent) renderView() {
|
||||
metadata,
|
||||
m.showToolDetails,
|
||||
isLastToolInvocation,
|
||||
false,
|
||||
)
|
||||
m.cache.Set(key, content)
|
||||
}
|
||||
@@ -202,6 +203,7 @@ func (m *messagesComponent) renderView() {
|
||||
metadata,
|
||||
m.showToolDetails,
|
||||
isLastToolInvocation,
|
||||
false,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -212,6 +212,11 @@ func (a appModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
case dialog.CompletionDialogCloseMsg:
|
||||
a.showCompletionDialog = false
|
||||
a.completions.SetProvider(a.completionManager.DefaultProvider())
|
||||
case client.EventInstallationUpdated:
|
||||
return a, toast.NewSuccessToast(
|
||||
"New version installed",
|
||||
toast.WithTitle("opencode updated to "+msg.Properties.Version+", restart to apply."),
|
||||
)
|
||||
case client.EventSessionUpdated:
|
||||
if msg.Properties.Info.Id == a.app.Session.Id {
|
||||
a.app.Session = &msg.Properties.Info
|
||||
@@ -229,6 +234,12 @@ func (a appModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
a.app.Messages = append(a.app.Messages, msg.Properties.Info)
|
||||
}
|
||||
}
|
||||
case client.EventSessionError:
|
||||
unknownError, err := msg.Properties.Error.AsUnknownError()
|
||||
if err == nil {
|
||||
slog.Error("Server error", "name", unknownError.Name, "message", unknownError.Data.Message)
|
||||
return a, toast.NewErrorToast(unknownError.Data.Message, toast.WithTitle(unknownError.Name))
|
||||
}
|
||||
case tea.WindowSizeMsg:
|
||||
msg.Height -= 2 // Make space for the status bar
|
||||
a.width, a.height = msg.Width, msg.Height
|
||||
@@ -243,12 +254,13 @@ func (a appModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
}
|
||||
a.layout.SetSize(a.width, a.height)
|
||||
case app.SessionSelectedMsg:
|
||||
var err error
|
||||
a.app.Session = msg
|
||||
a.app.Messages, err = a.app.ListMessages(context.Background(), msg.Id)
|
||||
messages, err := a.app.ListMessages(context.Background(), msg.Id)
|
||||
if err != nil {
|
||||
slog.Error("Failed to list messages", "error", err)
|
||||
return a, toast.NewErrorToast("Failed to open session")
|
||||
}
|
||||
a.app.Session = msg
|
||||
a.app.Messages = messages
|
||||
case app.ModelSelectedMsg:
|
||||
a.app.Provider = &msg.Provider
|
||||
a.app.Model = &msg.Model
|
||||
|
||||
@@ -525,6 +525,9 @@
|
||||
{
|
||||
"$ref": "#/components/schemas/Event.storage.write"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/Event.installation.updated"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/Event.lsp.client.diagnostics"
|
||||
},
|
||||
@@ -537,9 +540,6 @@
|
||||
{
|
||||
"$ref": "#/components/schemas/Event.message.part.updated"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/Event.installation.updated"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/Event.session.updated"
|
||||
},
|
||||
@@ -551,11 +551,11 @@
|
||||
"propertyName": "type",
|
||||
"mapping": {
|
||||
"storage.write": "#/components/schemas/Event.storage.write",
|
||||
"installation.updated": "#/components/schemas/Event.installation.updated",
|
||||
"lsp.client.diagnostics": "#/components/schemas/Event.lsp.client.diagnostics",
|
||||
"permission.updated": "#/components/schemas/Event.permission.updated",
|
||||
"message.updated": "#/components/schemas/Event.message.updated",
|
||||
"message.part.updated": "#/components/schemas/Event.message.part.updated",
|
||||
"installation.updated": "#/components/schemas/Event.installation.updated",
|
||||
"session.updated": "#/components/schemas/Event.session.updated",
|
||||
"session.error": "#/components/schemas/Event.session.error"
|
||||
}
|
||||
@@ -586,6 +586,30 @@
|
||||
"properties"
|
||||
]
|
||||
},
|
||||
"Event.installation.updated": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"const": "installation.updated"
|
||||
},
|
||||
"properties": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"version": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"version"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type",
|
||||
"properties"
|
||||
]
|
||||
},
|
||||
"Event.lsp.client.diagnostics": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -1201,30 +1225,6 @@
|
||||
"properties"
|
||||
]
|
||||
},
|
||||
"Event.installation.updated": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"const": "installation.updated"
|
||||
},
|
||||
"properties": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"version": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"version"
|
||||
]
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"type",
|
||||
"properties"
|
||||
]
|
||||
},
|
||||
"Event.session.updated": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -1391,13 +1391,16 @@
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"$schema": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"description": "JSON schema reference for configuration validation"
|
||||
},
|
||||
"theme": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"description": "Theme name to use for the interface"
|
||||
},
|
||||
"keybinds": {
|
||||
"$ref": "#/components/schemas/Config.Keybinds"
|
||||
"$ref": "#/components/schemas/Config.Keybinds",
|
||||
"description": "Custom keybind configurations"
|
||||
},
|
||||
"autoshare": {
|
||||
"type": "boolean",
|
||||
@@ -1508,7 +1511,8 @@
|
||||
"required": [
|
||||
"models"
|
||||
]
|
||||
}
|
||||
},
|
||||
"description": "Custom provider configurations and model overrides"
|
||||
},
|
||||
"mcp": {
|
||||
"type": "object",
|
||||
@@ -1528,7 +1532,8 @@
|
||||
"remote": "#/components/schemas/Config.McpRemote"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "MCP (Model Context Protocol) server configurations"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -1536,85 +1541,112 @@
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"leader": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"description": "Leader key for keybind combinations"
|
||||
},
|
||||
"help": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"description": "Show help dialog"
|
||||
},
|
||||
"editor_open": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"description": "Open external editor"
|
||||
},
|
||||
"session_new": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"description": "Create a new session"
|
||||
},
|
||||
"session_list": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"description": "List all sessions"
|
||||
},
|
||||
"session_share": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"description": "Share current session"
|
||||
},
|
||||
"session_interrupt": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"description": "Interrupt current session"
|
||||
},
|
||||
"session_compact": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"description": "Toggle compact mode for session"
|
||||
},
|
||||
"tool_details": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"description": "Show tool details"
|
||||
},
|
||||
"model_list": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"description": "List available models"
|
||||
},
|
||||
"theme_list": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"description": "List available themes"
|
||||
},
|
||||
"project_init": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"description": "Initialize project configuration"
|
||||
},
|
||||
"input_clear": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"description": "Clear input field"
|
||||
},
|
||||
"input_paste": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"description": "Paste from clipboard"
|
||||
},
|
||||
"input_submit": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"description": "Submit input"
|
||||
},
|
||||
"input_newline": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"description": "Insert newline in input"
|
||||
},
|
||||
"history_previous": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"description": "Navigate to previous history item"
|
||||
},
|
||||
"history_next": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"description": "Navigate to next history item"
|
||||
},
|
||||
"messages_page_up": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"description": "Scroll messages up by one page"
|
||||
},
|
||||
"messages_page_down": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"description": "Scroll messages down by one page"
|
||||
},
|
||||
"messages_half_page_up": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"description": "Scroll messages up by half page"
|
||||
},
|
||||
"messages_half_page_down": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"description": "Scroll messages down by half page"
|
||||
},
|
||||
"messages_previous": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"description": "Navigate to previous message"
|
||||
},
|
||||
"messages_next": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"description": "Navigate to next message"
|
||||
},
|
||||
"messages_first": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"description": "Navigate to first message"
|
||||
},
|
||||
"messages_last": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"description": "Navigate to last message"
|
||||
},
|
||||
"app_exit": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"description": "Exit the application"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -1723,19 +1755,22 @@
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"const": "local"
|
||||
"const": "local",
|
||||
"description": "Type of MCP server connection"
|
||||
},
|
||||
"command": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"description": "Command and arguments to run the MCP server"
|
||||
},
|
||||
"environment": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"description": "Environment variables to set when running the MCP server"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -1748,10 +1783,12 @@
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
"const": "remote"
|
||||
"const": "remote",
|
||||
"description": "Type of MCP server connection"
|
||||
},
|
||||
"url": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"description": "URL of the remote MCP server"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
|
||||
@@ -41,6 +41,7 @@ type AppInfo struct {
|
||||
|
||||
// ConfigInfo defines model for Config.Info.
|
||||
type ConfigInfo struct {
|
||||
// Schema JSON schema reference for configuration validation
|
||||
Schema *string `json:"$schema,omitempty"`
|
||||
|
||||
// Autoshare Share newly created sessions automatically
|
||||
@@ -50,12 +51,16 @@ type ConfigInfo struct {
|
||||
Autoupdate *bool `json:"autoupdate,omitempty"`
|
||||
|
||||
// DisabledProviders Disable providers that are loaded automatically
|
||||
DisabledProviders *[]string `json:"disabled_providers,omitempty"`
|
||||
Keybinds *ConfigKeybinds `json:"keybinds,omitempty"`
|
||||
Mcp *map[string]ConfigInfo_Mcp_AdditionalProperties `json:"mcp,omitempty"`
|
||||
DisabledProviders *[]string `json:"disabled_providers,omitempty"`
|
||||
Keybinds *ConfigKeybinds `json:"keybinds,omitempty"`
|
||||
|
||||
// Mcp MCP (Model Context Protocol) server configurations
|
||||
Mcp *map[string]ConfigInfo_Mcp_AdditionalProperties `json:"mcp,omitempty"`
|
||||
|
||||
// Model Model to use in the format of provider/model, eg anthropic/claude-2
|
||||
Model *string `json:"model,omitempty"`
|
||||
Model *string `json:"model,omitempty"`
|
||||
|
||||
// Provider Custom provider configurations and model overrides
|
||||
Provider *map[string]struct {
|
||||
Api *string `json:"api,omitempty"`
|
||||
Env *[]string `json:"env,omitempty"`
|
||||
@@ -81,6 +86,8 @@ type ConfigInfo struct {
|
||||
Npm *string `json:"npm,omitempty"`
|
||||
Options *map[string]interface{} `json:"options,omitempty"`
|
||||
} `json:"provider,omitempty"`
|
||||
|
||||
// Theme Theme name to use for the interface
|
||||
Theme *string `json:"theme,omitempty"`
|
||||
}
|
||||
|
||||
@@ -91,46 +98,107 @@ type ConfigInfo_Mcp_AdditionalProperties struct {
|
||||
|
||||
// ConfigKeybinds defines model for Config.Keybinds.
|
||||
type ConfigKeybinds struct {
|
||||
AppExit *string `json:"app_exit,omitempty"`
|
||||
EditorOpen *string `json:"editor_open,omitempty"`
|
||||
Help *string `json:"help,omitempty"`
|
||||
HistoryNext *string `json:"history_next,omitempty"`
|
||||
HistoryPrevious *string `json:"history_previous,omitempty"`
|
||||
InputClear *string `json:"input_clear,omitempty"`
|
||||
InputNewline *string `json:"input_newline,omitempty"`
|
||||
InputPaste *string `json:"input_paste,omitempty"`
|
||||
InputSubmit *string `json:"input_submit,omitempty"`
|
||||
Leader *string `json:"leader,omitempty"`
|
||||
MessagesFirst *string `json:"messages_first,omitempty"`
|
||||
// AppExit Exit the application
|
||||
AppExit *string `json:"app_exit,omitempty"`
|
||||
|
||||
// EditorOpen Open external editor
|
||||
EditorOpen *string `json:"editor_open,omitempty"`
|
||||
|
||||
// Help Show help dialog
|
||||
Help *string `json:"help,omitempty"`
|
||||
|
||||
// HistoryNext Navigate to next history item
|
||||
HistoryNext *string `json:"history_next,omitempty"`
|
||||
|
||||
// HistoryPrevious Navigate to previous history item
|
||||
HistoryPrevious *string `json:"history_previous,omitempty"`
|
||||
|
||||
// InputClear Clear input field
|
||||
InputClear *string `json:"input_clear,omitempty"`
|
||||
|
||||
// InputNewline Insert newline in input
|
||||
InputNewline *string `json:"input_newline,omitempty"`
|
||||
|
||||
// InputPaste Paste from clipboard
|
||||
InputPaste *string `json:"input_paste,omitempty"`
|
||||
|
||||
// InputSubmit Submit input
|
||||
InputSubmit *string `json:"input_submit,omitempty"`
|
||||
|
||||
// Leader Leader key for keybind combinations
|
||||
Leader *string `json:"leader,omitempty"`
|
||||
|
||||
// MessagesFirst Navigate to first message
|
||||
MessagesFirst *string `json:"messages_first,omitempty"`
|
||||
|
||||
// MessagesHalfPageDown Scroll messages down by half page
|
||||
MessagesHalfPageDown *string `json:"messages_half_page_down,omitempty"`
|
||||
MessagesHalfPageUp *string `json:"messages_half_page_up,omitempty"`
|
||||
MessagesLast *string `json:"messages_last,omitempty"`
|
||||
MessagesNext *string `json:"messages_next,omitempty"`
|
||||
MessagesPageDown *string `json:"messages_page_down,omitempty"`
|
||||
MessagesPageUp *string `json:"messages_page_up,omitempty"`
|
||||
MessagesPrevious *string `json:"messages_previous,omitempty"`
|
||||
ModelList *string `json:"model_list,omitempty"`
|
||||
ProjectInit *string `json:"project_init,omitempty"`
|
||||
SessionCompact *string `json:"session_compact,omitempty"`
|
||||
SessionInterrupt *string `json:"session_interrupt,omitempty"`
|
||||
SessionList *string `json:"session_list,omitempty"`
|
||||
SessionNew *string `json:"session_new,omitempty"`
|
||||
SessionShare *string `json:"session_share,omitempty"`
|
||||
ThemeList *string `json:"theme_list,omitempty"`
|
||||
ToolDetails *string `json:"tool_details,omitempty"`
|
||||
|
||||
// MessagesHalfPageUp Scroll messages up by half page
|
||||
MessagesHalfPageUp *string `json:"messages_half_page_up,omitempty"`
|
||||
|
||||
// MessagesLast Navigate to last message
|
||||
MessagesLast *string `json:"messages_last,omitempty"`
|
||||
|
||||
// MessagesNext Navigate to next message
|
||||
MessagesNext *string `json:"messages_next,omitempty"`
|
||||
|
||||
// MessagesPageDown Scroll messages down by one page
|
||||
MessagesPageDown *string `json:"messages_page_down,omitempty"`
|
||||
|
||||
// MessagesPageUp Scroll messages up by one page
|
||||
MessagesPageUp *string `json:"messages_page_up,omitempty"`
|
||||
|
||||
// MessagesPrevious Navigate to previous message
|
||||
MessagesPrevious *string `json:"messages_previous,omitempty"`
|
||||
|
||||
// ModelList List available models
|
||||
ModelList *string `json:"model_list,omitempty"`
|
||||
|
||||
// ProjectInit Initialize project configuration
|
||||
ProjectInit *string `json:"project_init,omitempty"`
|
||||
|
||||
// SessionCompact Toggle compact mode for session
|
||||
SessionCompact *string `json:"session_compact,omitempty"`
|
||||
|
||||
// SessionInterrupt Interrupt current session
|
||||
SessionInterrupt *string `json:"session_interrupt,omitempty"`
|
||||
|
||||
// SessionList List all sessions
|
||||
SessionList *string `json:"session_list,omitempty"`
|
||||
|
||||
// SessionNew Create a new session
|
||||
SessionNew *string `json:"session_new,omitempty"`
|
||||
|
||||
// SessionShare Share current session
|
||||
SessionShare *string `json:"session_share,omitempty"`
|
||||
|
||||
// ThemeList List available themes
|
||||
ThemeList *string `json:"theme_list,omitempty"`
|
||||
|
||||
// ToolDetails Show tool details
|
||||
ToolDetails *string `json:"tool_details,omitempty"`
|
||||
}
|
||||
|
||||
// ConfigMcpLocal defines model for Config.McpLocal.
|
||||
type ConfigMcpLocal struct {
|
||||
Command []string `json:"command"`
|
||||
// Command Command and arguments to run the MCP server
|
||||
Command []string `json:"command"`
|
||||
|
||||
// Environment Environment variables to set when running the MCP server
|
||||
Environment *map[string]string `json:"environment,omitempty"`
|
||||
Type string `json:"type"`
|
||||
|
||||
// Type Type of MCP server connection
|
||||
Type string `json:"type"`
|
||||
}
|
||||
|
||||
// ConfigMcpRemote defines model for Config.McpRemote.
|
||||
type ConfigMcpRemote struct {
|
||||
// Type Type of MCP server connection
|
||||
Type string `json:"type"`
|
||||
Url string `json:"url"`
|
||||
|
||||
// Url URL of the remote MCP server
|
||||
Url string `json:"url"`
|
||||
}
|
||||
|
||||
// Error defines model for Error.
|
||||
@@ -684,6 +752,34 @@ func (t *Event) MergeEventStorageWrite(v EventStorageWrite) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// AsEventInstallationUpdated returns the union data inside the Event as a EventInstallationUpdated
|
||||
func (t Event) AsEventInstallationUpdated() (EventInstallationUpdated, error) {
|
||||
var body EventInstallationUpdated
|
||||
err := json.Unmarshal(t.union, &body)
|
||||
return body, err
|
||||
}
|
||||
|
||||
// FromEventInstallationUpdated overwrites any union data inside the Event as the provided EventInstallationUpdated
|
||||
func (t *Event) FromEventInstallationUpdated(v EventInstallationUpdated) error {
|
||||
v.Type = "installation.updated"
|
||||
b, err := json.Marshal(v)
|
||||
t.union = b
|
||||
return err
|
||||
}
|
||||
|
||||
// MergeEventInstallationUpdated performs a merge with any union data inside the Event, using the provided EventInstallationUpdated
|
||||
func (t *Event) MergeEventInstallationUpdated(v EventInstallationUpdated) error {
|
||||
v.Type = "installation.updated"
|
||||
b, err := json.Marshal(v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
merged, err := runtime.JSONMerge(t.union, b)
|
||||
t.union = merged
|
||||
return err
|
||||
}
|
||||
|
||||
// AsEventLspClientDiagnostics returns the union data inside the Event as a EventLspClientDiagnostics
|
||||
func (t Event) AsEventLspClientDiagnostics() (EventLspClientDiagnostics, error) {
|
||||
var body EventLspClientDiagnostics
|
||||
@@ -796,34 +892,6 @@ func (t *Event) MergeEventMessagePartUpdated(v EventMessagePartUpdated) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// AsEventInstallationUpdated returns the union data inside the Event as a EventInstallationUpdated
|
||||
func (t Event) AsEventInstallationUpdated() (EventInstallationUpdated, error) {
|
||||
var body EventInstallationUpdated
|
||||
err := json.Unmarshal(t.union, &body)
|
||||
return body, err
|
||||
}
|
||||
|
||||
// FromEventInstallationUpdated overwrites any union data inside the Event as the provided EventInstallationUpdated
|
||||
func (t *Event) FromEventInstallationUpdated(v EventInstallationUpdated) error {
|
||||
v.Type = "installation.updated"
|
||||
b, err := json.Marshal(v)
|
||||
t.union = b
|
||||
return err
|
||||
}
|
||||
|
||||
// MergeEventInstallationUpdated performs a merge with any union data inside the Event, using the provided EventInstallationUpdated
|
||||
func (t *Event) MergeEventInstallationUpdated(v EventInstallationUpdated) error {
|
||||
v.Type = "installation.updated"
|
||||
b, err := json.Marshal(v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
merged, err := runtime.JSONMerge(t.union, b)
|
||||
t.union = merged
|
||||
return err
|
||||
}
|
||||
|
||||
// AsEventSessionUpdated returns the union data inside the Event as a EventSessionUpdated
|
||||
func (t Event) AsEventSessionUpdated() (EventSessionUpdated, error) {
|
||||
var body EventSessionUpdated
|
||||
|
||||
Reference in New Issue
Block a user