mirror of
https://github.com/sst/opencode.git
synced 2025-08-29 17:34:11 +00:00
Merge branch 'dev' into project
This commit is contained in:
commit
61468546be
178 changed files with 10538 additions and 3764 deletions
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"$schema": "https://json.schemastore.org/package.json",
|
||||
"name": "@opencode-ai/sdk",
|
||||
"version": "0.4.40",
|
||||
"version": "0.5.18",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"typecheck": "tsc --noEmit"
|
||||
|
@ -10,6 +10,14 @@
|
|||
".": {
|
||||
"development": "./src/index.ts",
|
||||
"import": "./dist/index.js"
|
||||
},
|
||||
"./client": {
|
||||
"development": "./src/client.ts",
|
||||
"import": "./dist/client.js"
|
||||
},
|
||||
"./server": {
|
||||
"development": "./src/server.ts",
|
||||
"import": "./dist/server.js"
|
||||
}
|
||||
},
|
||||
"files": [
|
||||
|
@ -19,5 +27,8 @@
|
|||
"typescript": "catalog:",
|
||||
"@hey-api/openapi-ts": "0.80.1",
|
||||
"@tsconfig/node22": "catalog:"
|
||||
},
|
||||
"dependencies": {
|
||||
"@hey-api/openapi-ts": "0.80.1"
|
||||
}
|
||||
}
|
||||
|
|
11
packages/sdk/js/src/client.ts
Normal file
11
packages/sdk/js/src/client.ts
Normal file
|
@ -0,0 +1,11 @@
|
|||
export * from "./gen/types.gen.js"
|
||||
export { type Config as OpencodeClientConfig, OpencodeClient }
|
||||
|
||||
import { createClient } from "./gen/client/client.js"
|
||||
import { type Config } from "./gen/client/types.js"
|
||||
import { OpencodeClient } from "./gen/sdk.gen.js"
|
||||
|
||||
export function createOpencodeClient(config?: Config) {
|
||||
const client = createClient(config)
|
||||
return new OpencodeClient({ client })
|
||||
}
|
|
@ -21,6 +21,8 @@ import type {
|
|||
SessionGetResponses,
|
||||
SessionUpdateData,
|
||||
SessionUpdateResponses,
|
||||
SessionChildrenData,
|
||||
SessionChildrenResponses,
|
||||
SessionInitData,
|
||||
SessionInitResponses,
|
||||
SessionAbortData,
|
||||
|
@ -37,12 +39,18 @@ import type {
|
|||
SessionChatResponses,
|
||||
SessionMessageData,
|
||||
SessionMessageResponses,
|
||||
SessionCommandData,
|
||||
SessionCommandResponses,
|
||||
SessionShellData,
|
||||
SessionShellResponses,
|
||||
SessionRevertData,
|
||||
SessionRevertResponses,
|
||||
SessionUnrevertData,
|
||||
SessionUnrevertResponses,
|
||||
PostSessionByIdPermissionsByPermissionIdData,
|
||||
PostSessionByIdPermissionsByPermissionIdResponses,
|
||||
CommandListData,
|
||||
CommandListResponses,
|
||||
ConfigProvidersData,
|
||||
ConfigProvidersResponses,
|
||||
FindTextData,
|
||||
|
@ -75,6 +83,11 @@ import type {
|
|||
TuiClearPromptResponses,
|
||||
TuiExecuteCommandData,
|
||||
TuiExecuteCommandResponses,
|
||||
TuiShowToastData,
|
||||
TuiShowToastResponses,
|
||||
AuthSetData,
|
||||
AuthSetResponses,
|
||||
AuthSetErrors,
|
||||
} from "./types.gen.js"
|
||||
import { client as _heyApiClient } from "./client.gen.js"
|
||||
|
||||
|
@ -203,6 +216,10 @@ class Session extends _HeyApiClient {
|
|||
return (options?.client ?? this._client).post<SessionCreateResponses, SessionCreateErrors, ThrowOnError>({
|
||||
url: "/session",
|
||||
...options,
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
...options?.headers,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -240,6 +257,16 @@ class Session extends _HeyApiClient {
|
|||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a session's children
|
||||
*/
|
||||
public children<ThrowOnError extends boolean = false>(options: Options<SessionChildrenData, ThrowOnError>) {
|
||||
return (options.client ?? this._client).get<SessionChildrenResponses, unknown, ThrowOnError>({
|
||||
url: "/session/{id}/children",
|
||||
...options,
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Analyze the app and create an AGENTS.md file
|
||||
*/
|
||||
|
@ -332,6 +359,34 @@ class Session extends _HeyApiClient {
|
|||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a new command to a session
|
||||
*/
|
||||
public command<ThrowOnError extends boolean = false>(options: Options<SessionCommandData, ThrowOnError>) {
|
||||
return (options.client ?? this._client).post<SessionCommandResponses, unknown, ThrowOnError>({
|
||||
url: "/session/{id}/command",
|
||||
...options,
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
...options.headers,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Run a shell command
|
||||
*/
|
||||
public shell<ThrowOnError extends boolean = false>(options: Options<SessionShellData, ThrowOnError>) {
|
||||
return (options.client ?? this._client).post<SessionShellResponses, unknown, ThrowOnError>({
|
||||
url: "/session/{id}/shell",
|
||||
...options,
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
...options.headers,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Revert a message
|
||||
*/
|
||||
|
@ -357,6 +412,18 @@ class Session extends _HeyApiClient {
|
|||
}
|
||||
}
|
||||
|
||||
class Command extends _HeyApiClient {
|
||||
/**
|
||||
* List all commands
|
||||
*/
|
||||
public list<ThrowOnError extends boolean = false>(options?: Options<CommandListData, ThrowOnError>) {
|
||||
return (options?.client ?? this._client).get<CommandListResponses, unknown, ThrowOnError>({
|
||||
url: "/command",
|
||||
...options,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
class Find extends _HeyApiClient {
|
||||
/**
|
||||
* Find text in files
|
||||
|
@ -487,7 +554,7 @@ class Tui extends _HeyApiClient {
|
|||
}
|
||||
|
||||
/**
|
||||
* Execute a TUI command (e.g. switch_agent)
|
||||
* Execute a TUI command (e.g. agent_cycle)
|
||||
*/
|
||||
public executeCommand<ThrowOnError extends boolean = false>(options?: Options<TuiExecuteCommandData, ThrowOnError>) {
|
||||
return (options?.client ?? this._client).post<TuiExecuteCommandResponses, unknown, ThrowOnError>({
|
||||
|
@ -499,6 +566,36 @@ class Tui extends _HeyApiClient {
|
|||
},
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a toast notification in the TUI
|
||||
*/
|
||||
public showToast<ThrowOnError extends boolean = false>(options?: Options<TuiShowToastData, ThrowOnError>) {
|
||||
return (options?.client ?? this._client).post<TuiShowToastResponses, unknown, ThrowOnError>({
|
||||
url: "/tui/show-toast",
|
||||
...options,
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
...options?.headers,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
class Auth extends _HeyApiClient {
|
||||
/**
|
||||
* Set authentication credentials
|
||||
*/
|
||||
public set<ThrowOnError extends boolean = false>(options: Options<AuthSetData, ThrowOnError>) {
|
||||
return (options.client ?? this._client).put<AuthSetResponses, AuthSetErrors, ThrowOnError>({
|
||||
url: "/auth/{id}",
|
||||
...options,
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
...options.headers,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export class OpencodeClient extends _HeyApiClient {
|
||||
|
@ -525,7 +622,9 @@ export class OpencodeClient extends _HeyApiClient {
|
|||
app = new App({ client: this._client })
|
||||
config = new Config({ client: this._client })
|
||||
session = new Session({ client: this._client })
|
||||
command = new Command({ client: this._client })
|
||||
find = new Find({ client: this._client })
|
||||
file = new File({ client: this._client })
|
||||
tui = new Tui({ client: this._client })
|
||||
auth = new Auth({ client: this._client })
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,9 +1,2 @@
|
|||
import { createClient } from "./gen/client/client.js"
|
||||
import { type Config } from "./gen/client/types.js"
|
||||
import { OpencodeClient } from "./gen/sdk.gen.js"
|
||||
export * from "./gen/types.gen.js"
|
||||
|
||||
export function createOpencodeClient(config?: Config) {
|
||||
const client = createClient(config)
|
||||
return new OpencodeClient({ client })
|
||||
}
|
||||
export * from "./client.js"
|
||||
export * from "./server.js"
|
||||
|
|
73
packages/sdk/js/src/server.ts
Normal file
73
packages/sdk/js/src/server.ts
Normal file
|
@ -0,0 +1,73 @@
|
|||
import { spawn } from "node:child_process"
|
||||
|
||||
export type ServerConfig = {
|
||||
hostname?: string
|
||||
port?: number
|
||||
signal?: AbortSignal
|
||||
timeout?: number
|
||||
}
|
||||
|
||||
export async function createOpencodeServer(config?: ServerConfig) {
|
||||
config = Object.assign(
|
||||
{
|
||||
hostname: "127.0.0.1",
|
||||
port: 4096,
|
||||
timeout: 5000,
|
||||
},
|
||||
config ?? {},
|
||||
)
|
||||
|
||||
const proc = spawn(`opencode`, [`serve`, `--hostname=${config.hostname}`, `--port=${config.port}`], {
|
||||
signal: config.signal,
|
||||
})
|
||||
|
||||
const url = await new Promise<string>((resolve, reject) => {
|
||||
const id = setTimeout(() => {
|
||||
reject(new Error(`Timeout waiting for server to start after ${config.timeout}ms`))
|
||||
}, config.timeout)
|
||||
let output = ""
|
||||
proc.stdout?.on("data", (chunk) => {
|
||||
output += chunk.toString()
|
||||
const lines = output.split("\n")
|
||||
for (const line of lines) {
|
||||
if (line.startsWith("opencode server listening")) {
|
||||
const match = line.match(/on\s+(https?:\/\/[^\s]+)/)
|
||||
if (!match) {
|
||||
throw new Error(`Failed to parse server url from output: ${line}`)
|
||||
}
|
||||
clearTimeout(id)
|
||||
resolve(match[1])
|
||||
return
|
||||
}
|
||||
}
|
||||
})
|
||||
proc.stderr?.on("data", (chunk) => {
|
||||
output += chunk.toString()
|
||||
})
|
||||
proc.on("exit", (code) => {
|
||||
clearTimeout(id)
|
||||
let msg = `Server exited with code ${code}`
|
||||
if (output.trim()) {
|
||||
msg += `\nServer output: ${output}`
|
||||
}
|
||||
reject(new Error(msg))
|
||||
})
|
||||
proc.on("error", (error) => {
|
||||
clearTimeout(id)
|
||||
reject(error)
|
||||
})
|
||||
if (config.signal) {
|
||||
config.signal.addEventListener("abort", () => {
|
||||
clearTimeout(id)
|
||||
reject(new Error("Aborted"))
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
return {
|
||||
url,
|
||||
close() {
|
||||
proc.kill()
|
||||
},
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue