Compare commits

..

5 Commits

Author SHA1 Message Date
Dax Raad 7dd0918d32 remove accidental opanai autoloader 2025-06-24 21:11:11 -04:00
Dax Raad 4b26b43855 added opencode serve command 2025-06-24 20:52:09 -04:00
Jay V 9d7cfda9fe docs: share page styles 2025-06-24 19:34:35 -04:00
Jay V a3cf18c905 docs: share page bash tool output 2025-06-24 19:28:51 -04:00
Aiden Cline 0b1a8ae699 fix: file completions replaced wrong text when paths overlap (#378) 2025-06-24 18:13:15 -05:00
9 changed files with 118 additions and 32 deletions
+50
View File
@@ -0,0 +1,50 @@
import { App } from "../../app/app"
import { Provider } from "../../provider/provider"
import { Server } from "../../server/server"
import { Share } from "../../share/share"
import { cmd } from "./cmd"
export const ServeCommand = cmd({
command: "serve",
builder: (yargs) =>
yargs
.option("port", {
alias: ["p"],
type: "number",
describe: "port to listen on",
default: 4096,
})
.option("hostname", {
alias: ["h"],
type: "string",
describe: "hostname to listen on",
default: "127.0.0.1",
}),
describe: "starts a headless opencode server",
handler: async (args) => {
const cwd = process.cwd()
await App.provide({ cwd }, async () => {
const providers = await Provider.list()
if (Object.keys(providers).length === 0) {
return "needs_provider"
}
const hostname = args.hostname
const port = args.port
await Share.init()
const server = Server.listen({
port,
hostname,
})
console.log(
`opencode server listening on http://${server.hostname}:${server.port}`,
)
await new Promise(() => {})
server.stop()
})
},
})
+8 -3
View File
@@ -21,13 +21,13 @@ import { Bus } from "./bus"
import { Config } from "./config/config"
import { NamedError } from "./util/error"
import { FormatError } from "./cli/error"
import { ServeCommand } from "./cli/cmd/serve"
const cancel = new AbortController()
const cli = yargs(hideBin(process.argv))
.scriptName("opencode")
.help("help", "show help")
.alias("help", "h")
.version("version", "show version number", Installation.VERSION)
.alias("version", "v")
.option("print-logs", {
@@ -61,10 +61,14 @@ const cli = yargs(hideBin(process.argv))
}
await Share.init()
const server = Server.listen()
const server = Server.listen({
port: 0,
})
let cmd = ["go", "run", "./main.go"]
let cwd = url.fileURLToPath(new URL("../../tui/cmd/opencode", import.meta.url))
let cwd = url.fileURLToPath(
new URL("../../tui/cmd/opencode", import.meta.url),
)
if (Bun.embeddedFiles.length > 0) {
const blob = Bun.embeddedFiles[0] as File
let binaryName = blob.name
@@ -134,6 +138,7 @@ const cli = yargs(hideBin(process.argv))
.command(ScrapCommand)
.command(AuthCommand)
.command(UpgradeCommand)
.command(ServeCommand)
.fail((msg) => {
if (
msg.startsWith("Unknown argument") ||
@@ -113,14 +113,6 @@ export namespace Provider {
},
}
},
openai: async () => {
return {
async getModel(sdk: any, modelID: string) {
return sdk.responses(modelID)
},
options: {},
}
},
"amazon-bedrock": async () => {
if (!process.env["AWS_PROFILE"] && !process.env["AWS_ACCESS_KEY_ID"])
return false
+3 -3
View File
@@ -579,10 +579,10 @@ export namespace Server {
return result
}
export function listen() {
export function listen(opts: { port: number; hostname: string }) {
const server = Bun.serve({
port: 0,
hostname: "0.0.0.0",
port: opts.port,
hostname: opts.hostname,
idleTimeout: 0,
fetch: app().fetch,
})
+1
View File
@@ -0,0 +1 @@
opencode-test
@@ -80,8 +80,15 @@ func (m *editorComponent) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
return m, tea.Batch(cmds...)
} else {
existingValue := m.textarea.Value()
modifiedValue := strings.Replace(existingValue, msg.SearchString, msg.CompletionValue, 1)
m.textarea.SetValue(modifiedValue + " ")
// Replace the current token (after last space)
lastSpaceIndex := strings.LastIndex(existingValue, " ")
if lastSpaceIndex == -1 {
m.textarea.SetValue(msg.CompletionValue + " ")
} else {
modifiedValue := existingValue[:lastSpaceIndex+1] + msg.CompletionValue
m.textarea.SetValue(modifiedValue + " ")
}
return m, nil
}
}
+36 -16
View File
@@ -463,6 +463,7 @@ function MarkdownPart(props: MarkdownPartProps) {
interface TerminalPartProps extends JSX.HTMLAttributes<HTMLDivElement> {
command: string
error?: string
result?: string
desc?: string
expand?: boolean
@@ -470,6 +471,7 @@ interface TerminalPartProps extends JSX.HTMLAttributes<HTMLDivElement> {
function TerminalPart(props: TerminalPartProps) {
const [local, rest] = splitProps(props, [
"command",
"error",
"result",
"desc",
"expand",
@@ -508,12 +510,25 @@ function TerminalPart(props: TerminalPartProps) {
</div>
<div data-section="content">
<CodeBlock lang="bash" code={local.command} />
<CodeBlock
lang="console"
onRendered={checkOverflow}
ref={(el) => (preEl = el)}
code={local.result || ""}
/>
<Switch>
<Match when={local.error}>
<CodeBlock
data-section="error"
lang="text"
onRendered={checkOverflow}
ref={(el) => (preEl = el)}
code={local.error || ""}
/>
</Match>
<Match when={local.result}>
<CodeBlock
lang="console"
onRendered={checkOverflow}
ref={(el) => (preEl = el)}
code={local.result || ""}
/>
</Match>
</Switch>
</div>
</div>
{((!local.expand && overflowed()) || expanded()) && (
@@ -1601,8 +1616,10 @@ export default function Share(props: {
}
>
{(_part) => {
const command = () => toolData()?.args.command
const desc = () => toolData()?.args.description
const command = () => toolData()?.metadata?.title
const desc = () => toolData()?.metadata?.description
const result = () => toolData()?.metadata?.stdout
const error = () => toolData()?.metadata?.stderr
return (
<div
@@ -1617,14 +1634,17 @@ export default function Share(props: {
<div></div>
</div>
<div data-section="content">
<div data-part-tool-body>
<TerminalPart
desc={desc()}
data-size="sm"
command={command()}
result={toolData()?.result}
/>
</div>
{command() && (
<div data-part-tool-body>
<TerminalPart
desc={desc()}
data-size="sm"
command={command()!}
result={result()}
error={error()}
/>
</div>
)}
<ToolFooter
time={toolData()?.duration || 0}
/>
@@ -2,6 +2,10 @@
pre {
--shiki-dark-bg: var(--sl-color-bg-surface) !important;
background-color: var(--sl-color-bg-surface) !important;
span {
white-space: break-spaces;
}
}
}
@@ -616,6 +616,13 @@
}
}
[data-section="error"] {
pre {
color: var(--sl-color-red) !important;
--shiki-dark: var(--sl-color-red) !important;
}
}
&[data-expanded="true"] {
pre {
display: block;