Refactor to support multiple instances inside single opencode process (#2360)

This release has a bunch of minor breaking changes if you are using opencode plugins or sdk

1. storage events have been removed (we might bring this back but had some issues)
2. concept of `app` is gone - there is a new concept called `project` and endpoints to list projects and get the current project
3. plugin receives `directory` which is cwd and `worktree` which is where the root of the project is if it's a git repo
4. the session.chat function has been renamed to session.prompt in sdk. it no longer requires model to be passed in (model is now an object)
5. every endpoint takes an optional `directory` parameter to operate as though opencode is running in that directory
This commit is contained in:
Dax
2025-09-01 17:15:49 -04:00
committed by GitHub
parent e2df3eb44d
commit f993541e0b
112 changed files with 4303 additions and 3159 deletions

View File

@@ -2,14 +2,16 @@
import type { Options as ClientOptions, TDataShape, Client } from "./client/index.js"
import type {
ProjectListData,
ProjectListResponses,
ProjectCurrentData,
ProjectCurrentResponses,
EventSubscribeData,
EventSubscribeResponses,
AppGetData,
AppGetResponses,
AppInitData,
AppInitResponses,
ConfigGetData,
ConfigGetResponses,
PathGetData,
PathGetResponses,
SessionListData,
SessionListResponses,
SessionCreateData,
@@ -35,8 +37,8 @@ import type {
SessionSummarizeResponses,
SessionMessagesData,
SessionMessagesResponses,
SessionChatData,
SessionChatResponses,
SessionPromptData,
SessionPromptResponses,
SessionMessageData,
SessionMessageResponses,
SessionCommandData,
@@ -120,6 +122,28 @@ class _HeyApiClient {
}
}
class Project extends _HeyApiClient {
/**
* List all projects
*/
public list<ThrowOnError extends boolean = false>(options?: Options<ProjectListData, ThrowOnError>) {
return (options?.client ?? this._client).get<ProjectListResponses, unknown, ThrowOnError>({
url: "/project",
...options,
})
}
/**
* Get the current project
*/
public current<ThrowOnError extends boolean = false>(options?: Options<ProjectCurrentData, ThrowOnError>) {
return (options?.client ?? this._client).get<ProjectCurrentResponses, unknown, ThrowOnError>({
url: "/project/current",
...options,
})
}
}
class Event extends _HeyApiClient {
/**
* Get events
@@ -132,52 +156,6 @@ class Event extends _HeyApiClient {
}
}
class App extends _HeyApiClient {
/**
* Get app info
*/
public get<ThrowOnError extends boolean = false>(options?: Options<AppGetData, ThrowOnError>) {
return (options?.client ?? this._client).get<AppGetResponses, unknown, ThrowOnError>({
url: "/app",
...options,
})
}
/**
* Initialize the app
*/
public init<ThrowOnError extends boolean = false>(options?: Options<AppInitData, ThrowOnError>) {
return (options?.client ?? this._client).post<AppInitResponses, unknown, ThrowOnError>({
url: "/app/init",
...options,
})
}
/**
* Write a log entry to the server logs
*/
public log<ThrowOnError extends boolean = false>(options?: Options<AppLogData, ThrowOnError>) {
return (options?.client ?? this._client).post<AppLogResponses, unknown, ThrowOnError>({
url: "/log",
...options,
headers: {
"Content-Type": "application/json",
...options?.headers,
},
})
}
/**
* List all agents
*/
public agents<ThrowOnError extends boolean = false>(options?: Options<AppAgentsData, ThrowOnError>) {
return (options?.client ?? this._client).get<AppAgentsResponses, unknown, ThrowOnError>({
url: "/agent",
...options,
})
}
}
class Config extends _HeyApiClient {
/**
* Get config info
@@ -200,6 +178,18 @@ class Config extends _HeyApiClient {
}
}
class Path extends _HeyApiClient {
/**
* Get the current path
*/
public get<ThrowOnError extends boolean = false>(options?: Options<PathGetData, ThrowOnError>) {
return (options?.client ?? this._client).get<PathGetResponses, unknown, ThrowOnError>({
url: "/path",
...options,
})
}
}
class Session extends _HeyApiClient {
/**
* List all sessions
@@ -340,8 +330,8 @@ class Session extends _HeyApiClient {
/**
* Create and send a new message to a session
*/
public chat<ThrowOnError extends boolean = false>(options: Options<SessionChatData, ThrowOnError>) {
return (options.client ?? this._client).post<SessionChatResponses, unknown, ThrowOnError>({
public prompt<ThrowOnError extends boolean = false>(options: Options<SessionPromptData, ThrowOnError>) {
return (options.client ?? this._client).post<SessionPromptResponses, unknown, ThrowOnError>({
url: "/session/{id}/message",
...options,
headers: {
@@ -490,6 +480,32 @@ class File extends _HeyApiClient {
}
}
class App extends _HeyApiClient {
/**
* Write a log entry to the server logs
*/
public log<ThrowOnError extends boolean = false>(options?: Options<AppLogData, ThrowOnError>) {
return (options?.client ?? this._client).post<AppLogResponses, unknown, ThrowOnError>({
url: "/log",
...options,
headers: {
"Content-Type": "application/json",
...options?.headers,
},
})
}
/**
* List all agents
*/
public agents<ThrowOnError extends boolean = false>(options?: Options<AppAgentsData, ThrowOnError>) {
return (options?.client ?? this._client).get<AppAgentsResponses, unknown, ThrowOnError>({
url: "/agent",
...options,
})
}
}
class Tui extends _HeyApiClient {
/**
* Append prompt to the TUI
@@ -630,13 +646,15 @@ export class OpencodeClient extends _HeyApiClient {
},
})
}
project = new Project({ client: this._client })
event = new Event({ client: this._client })
app = new App({ client: this._client })
config = new Config({ client: this._client })
path = new Path({ 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 })
app = new App({ client: this._client })
tui = new Tui({ client: this._client })
auth = new Auth({ client: this._client })
}

View File

@@ -1,5 +1,15 @@
// This file is auto-generated by @hey-api/openapi-ts
export type Project = {
id: string
worktree: string
vcs?: "git"
time: {
created: number
initialized?: number
}
}
export type Event =
| ({
type: "installation.updated"
@@ -19,9 +29,6 @@ export type Event =
| ({
type: "message.part.removed"
} & EventMessagePartRemoved)
| ({
type: "storage.write"
} & EventStorageWrite)
| ({
type: "permission.updated"
} & EventPermissionUpdated)
@@ -46,12 +53,6 @@ export type Event =
| ({
type: "server.connected"
} & EventServerConnected)
| ({
type: "file.watcher.updated"
} & EventFileWatcherUpdated)
| ({
type: "ide.installed"
} & EventIdeInstalled)
export type EventInstallationUpdated = {
type: "installation.updated"
@@ -420,14 +421,6 @@ export type EventMessagePartRemoved = {
}
}
export type EventStorageWrite = {
type: "storage.write"
properties: {
key: string
content?: unknown
}
}
export type EventPermissionUpdated = {
type: "permission.updated"
properties: Permission
@@ -474,6 +467,8 @@ export type EventSessionUpdated = {
export type Session = {
id: string
projectID: string
directory: string
parentID?: string
share?: {
url: string
@@ -533,37 +528,6 @@ export type EventServerConnected = {
}
}
export type EventFileWatcherUpdated = {
type: "file.watcher.updated"
properties: {
file: string
event: "rename" | "change"
}
}
export type EventIdeInstalled = {
type: "ide.installed"
properties: {
ide: string
}
}
export type App = {
hostname: string
git: boolean
path: {
home: string
config: string
data: string
root: string
cwd: string
state: string
}
time: {
initialized?: number
}
}
export type Config = {
/**
* JSON schema reference for configuration validation
@@ -681,7 +645,11 @@ export type Config = {
options?: {
apiKey?: string
baseURL?: string
[key: string]: unknown | string | undefined
/**
* Timeout in milliseconds for requests to this provider. Default is 300000 (5 minutes). Set to false to disable timeout.
*/
timeout?: number | false
[key: string]: unknown | string | (number | false) | undefined
}
}
}
@@ -1085,6 +1053,13 @@ export type McpRemoteConfig = {
export type LayoutConfig = "auto" | "stretch"
export type Path = {
state: string
config: string
worktree: string
directory: string
}
export type _Error = {
data: {
[key: string]: unknown
@@ -1209,10 +1184,48 @@ export type WellKnownAuth = {
token: string
}
export type ProjectListData = {
body?: never
path?: never
query?: {
directory?: string
}
url: "/project"
}
export type ProjectListResponses = {
/**
* List of projects
*/
200: Array<Project>
}
export type ProjectListResponse = ProjectListResponses[keyof ProjectListResponses]
export type ProjectCurrentData = {
body?: never
path?: never
query?: {
directory?: string
}
url: "/project/current"
}
export type ProjectCurrentResponses = {
/**
* Current project
*/
200: Project
}
export type ProjectCurrentResponse = ProjectCurrentResponses[keyof ProjectCurrentResponses]
export type EventSubscribeData = {
body?: never
path?: never
query?: never
query?: {
directory?: string
}
url: "/event"
}
@@ -1225,42 +1238,12 @@ export type EventSubscribeResponses = {
export type EventSubscribeResponse = EventSubscribeResponses[keyof EventSubscribeResponses]
export type AppGetData = {
body?: never
path?: never
query?: never
url: "/app"
}
export type AppGetResponses = {
/**
* 200
*/
200: App
}
export type AppGetResponse = AppGetResponses[keyof AppGetResponses]
export type AppInitData = {
body?: never
path?: never
query?: never
url: "/app/init"
}
export type AppInitResponses = {
/**
* Initialize the app
*/
200: boolean
}
export type AppInitResponse = AppInitResponses[keyof AppInitResponses]
export type ConfigGetData = {
body?: never
path?: never
query?: never
query?: {
directory?: string
}
url: "/config"
}
@@ -1273,10 +1256,30 @@ export type ConfigGetResponses = {
export type ConfigGetResponse = ConfigGetResponses[keyof ConfigGetResponses]
export type PathGetData = {
body?: never
path?: never
query?: {
directory?: string
}
url: "/path"
}
export type PathGetResponses = {
/**
* Path
*/
200: Path
}
export type PathGetResponse = PathGetResponses[keyof PathGetResponses]
export type SessionListData = {
body?: never
path?: never
query?: never
query?: {
directory?: string
}
url: "/session"
}
@@ -1295,7 +1298,9 @@ export type SessionCreateData = {
title?: string
}
path?: never
query?: never
query?: {
directory?: string
}
url: "/session"
}
@@ -1322,7 +1327,9 @@ export type SessionDeleteData = {
path: {
id: string
}
query?: never
query?: {
directory?: string
}
url: "/session/{id}"
}
@@ -1340,7 +1347,9 @@ export type SessionGetData = {
path: {
id: string
}
query?: never
query?: {
directory?: string
}
url: "/session/{id}"
}
@@ -1360,7 +1369,9 @@ export type SessionUpdateData = {
path: {
id: string
}
query?: never
query?: {
directory?: string
}
url: "/session/{id}"
}
@@ -1378,7 +1389,9 @@ export type SessionChildrenData = {
path: {
id: string
}
query?: never
query?: {
directory?: string
}
url: "/session/{id}/children"
}
@@ -1403,7 +1416,9 @@ export type SessionInitData = {
*/
id: string
}
query?: never
query?: {
directory?: string
}
url: "/session/{id}/init"
}
@@ -1421,7 +1436,9 @@ export type SessionAbortData = {
path: {
id: string
}
query?: never
query?: {
directory?: string
}
url: "/session/{id}/abort"
}
@@ -1439,7 +1456,9 @@ export type SessionUnshareData = {
path: {
id: string
}
query?: never
query?: {
directory?: string
}
url: "/session/{id}/share"
}
@@ -1457,7 +1476,9 @@ export type SessionShareData = {
path: {
id: string
}
query?: never
query?: {
directory?: string
}
url: "/session/{id}/share"
}
@@ -1481,7 +1502,9 @@ export type SessionSummarizeData = {
*/
id: string
}
query?: never
query?: {
directory?: string
}
url: "/session/{id}/summarize"
}
@@ -1502,7 +1525,9 @@ export type SessionMessagesData = {
*/
id: string
}
query?: never
query?: {
directory?: string
}
url: "/session/{id}/message"
}
@@ -1518,11 +1543,13 @@ export type SessionMessagesResponses = {
export type SessionMessagesResponse = SessionMessagesResponses[keyof SessionMessagesResponses]
export type SessionChatData = {
export type SessionPromptData = {
body?: {
messageID?: string
providerID: string
modelID: string
model?: {
providerID: string
modelID: string
}
agent?: string
system?: string
tools?: {
@@ -1546,11 +1573,13 @@ export type SessionChatData = {
*/
id: string
}
query?: never
query?: {
directory?: string
}
url: "/session/{id}/message"
}
export type SessionChatResponses = {
export type SessionPromptResponses = {
/**
* Created message
*/
@@ -1560,7 +1589,7 @@ export type SessionChatResponses = {
}
}
export type SessionChatResponse = SessionChatResponses[keyof SessionChatResponses]
export type SessionPromptResponse = SessionPromptResponses[keyof SessionPromptResponses]
export type SessionMessageData = {
body?: never
@@ -1574,7 +1603,9 @@ export type SessionMessageData = {
*/
messageID: string
}
query?: never
query?: {
directory?: string
}
url: "/session/{id}/message/{messageID}"
}
@@ -1604,7 +1635,9 @@ export type SessionCommandData = {
*/
id: string
}
query?: never
query?: {
directory?: string
}
url: "/session/{id}/command"
}
@@ -1631,7 +1664,9 @@ export type SessionShellData = {
*/
id: string
}
query?: never
query?: {
directory?: string
}
url: "/session/{id}/shell"
}
@@ -1652,7 +1687,9 @@ export type SessionRevertData = {
path: {
id: string
}
query?: never
query?: {
directory?: string
}
url: "/session/{id}/revert"
}
@@ -1670,7 +1707,9 @@ export type SessionUnrevertData = {
path: {
id: string
}
query?: never
query?: {
directory?: string
}
url: "/session/{id}/unrevert"
}
@@ -1691,7 +1730,9 @@ export type PostSessionByIdPermissionsByPermissionIdData = {
id: string
permissionID: string
}
query?: never
query?: {
directory?: string
}
url: "/session/{id}/permissions/{permissionID}"
}
@@ -1708,7 +1749,9 @@ export type PostSessionByIdPermissionsByPermissionIdResponse =
export type CommandListData = {
body?: never
path?: never
query?: never
query?: {
directory?: string
}
url: "/command"
}
@@ -1724,7 +1767,9 @@ export type CommandListResponse = CommandListResponses[keyof CommandListResponse
export type ConfigProvidersData = {
body?: never
path?: never
query?: never
query?: {
directory?: string
}
url: "/config/providers"
}
@@ -1746,6 +1791,7 @@ export type FindTextData = {
body?: never
path?: never
query: {
directory?: string
pattern: string
}
url: "/find"
@@ -1780,6 +1826,7 @@ export type FindFilesData = {
body?: never
path?: never
query: {
directory?: string
query: string
}
url: "/find/file"
@@ -1798,6 +1845,7 @@ export type FindSymbolsData = {
body?: never
path?: never
query: {
directory?: string
query: string
}
url: "/find/symbol"
@@ -1816,6 +1864,7 @@ export type FileListData = {
body?: never
path?: never
query: {
directory?: string
path: string
}
url: "/file"
@@ -1834,6 +1883,7 @@ export type FileReadData = {
body?: never
path?: never
query: {
directory?: string
path: string
}
url: "/file/content"
@@ -1854,7 +1904,9 @@ export type FileReadResponse = FileReadResponses[keyof FileReadResponses]
export type FileStatusData = {
body?: never
path?: never
query?: never
query?: {
directory?: string
}
url: "/file/status"
}
@@ -1889,7 +1941,9 @@ export type AppLogData = {
}
}
path?: never
query?: never
query?: {
directory?: string
}
url: "/log"
}
@@ -1905,7 +1959,9 @@ export type AppLogResponse = AppLogResponses[keyof AppLogResponses]
export type AppAgentsData = {
body?: never
path?: never
query?: never
query?: {
directory?: string
}
url: "/agent"
}
@@ -1923,7 +1979,9 @@ export type TuiAppendPromptData = {
text: string
}
path?: never
query?: never
query?: {
directory?: string
}
url: "/tui/append-prompt"
}
@@ -1939,7 +1997,9 @@ export type TuiAppendPromptResponse = TuiAppendPromptResponses[keyof TuiAppendPr
export type TuiOpenHelpData = {
body?: never
path?: never
query?: never
query?: {
directory?: string
}
url: "/tui/open-help"
}
@@ -1955,7 +2015,9 @@ export type TuiOpenHelpResponse = TuiOpenHelpResponses[keyof TuiOpenHelpResponse
export type TuiOpenSessionsData = {
body?: never
path?: never
query?: never
query?: {
directory?: string
}
url: "/tui/open-sessions"
}
@@ -1971,7 +2033,9 @@ export type TuiOpenSessionsResponse = TuiOpenSessionsResponses[keyof TuiOpenSess
export type TuiOpenThemesData = {
body?: never
path?: never
query?: never
query?: {
directory?: string
}
url: "/tui/open-themes"
}
@@ -1987,7 +2051,9 @@ export type TuiOpenThemesResponse = TuiOpenThemesResponses[keyof TuiOpenThemesRe
export type TuiOpenModelsData = {
body?: never
path?: never
query?: never
query?: {
directory?: string
}
url: "/tui/open-models"
}
@@ -2003,7 +2069,9 @@ export type TuiOpenModelsResponse = TuiOpenModelsResponses[keyof TuiOpenModelsRe
export type TuiSubmitPromptData = {
body?: never
path?: never
query?: never
query?: {
directory?: string
}
url: "/tui/submit-prompt"
}
@@ -2019,7 +2087,9 @@ export type TuiSubmitPromptResponse = TuiSubmitPromptResponses[keyof TuiSubmitPr
export type TuiClearPromptData = {
body?: never
path?: never
query?: never
query?: {
directory?: string
}
url: "/tui/clear-prompt"
}
@@ -2037,7 +2107,9 @@ export type TuiExecuteCommandData = {
command: string
}
path?: never
query?: never
query?: {
directory?: string
}
url: "/tui/execute-command"
}
@@ -2057,7 +2129,9 @@ export type TuiShowToastData = {
variant: "info" | "success" | "warning" | "error"
}
path?: never
query?: never
query?: {
directory?: string
}
url: "/tui/show-toast"
}
@@ -2075,7 +2149,9 @@ export type AuthSetData = {
path: {
id: string
}
query?: never
query?: {
directory?: string
}
url: "/auth/{id}"
}