1package soy.iko.opencode.data.network
3import soy.iko.opencode.data.model.Agent
4import soy.iko.opencode.data.model.Command
5import soy.iko.opencode.data.model.CommandRequest
6import soy.iko.opencode.data.model.CreateSessionRequest
7import soy.iko.opencode.data.model.FileContent
8import soy.iko.opencode.data.model.FileNode
9import soy.iko.opencode.data.model.FileStatusEntry
10import soy.iko.opencode.data.model.MessageWithParts
11import soy.iko.opencode.data.model.ModelRef
12import soy.iko.opencode.data.model.PermissionReplyBody
13import soy.iko.opencode.data.model.PermissionResponse
14import soy.iko.opencode.data.model.PromptPart
15import soy.iko.opencode.data.model.PromptRequest
16import soy.iko.opencode.data.model.ProvidersResponse
17import soy.iko.opencode.data.model.Session
18import soy.iko.opencode.data.model.UpdateSessionRequest
19import io.ktor.client.HttpClient
20import io.ktor.client.call.body
21import io.ktor.client.request.delete
22import io.ktor.client.request.get
23import io.ktor.client.request.parameter
24import io.ktor.client.request.patch
25import io.ktor.client.request.post
26import io.ktor.client.request.setBody
27import io.ktor.http.ContentType
28import io.ktor.http.contentType
31 * Request/response wrapper over the opencode REST endpoints. The long-lived `/event`
32 * SSE stream lives in [EventStreamClient]; everything else is here.
34class OpencodeApiClient(private val client: HttpClient) {
36 /** Lightweight connectivity check used by the connect screen. */
37 suspend fun ping(): Boolean {
38 client.get("global/health")
42 suspend fun listSessions(): List<Session> =
43 client.get("session").body()
45 suspend fun createSession(title: String? = null): Session =
46 client.post("session") {
47 contentType(ContentType.Application.Json)
48 setBody(CreateSessionRequest(title = title))
51 suspend fun updateSession(id: String, title: String): Session =
52 client.patch("session/$id") {
53 contentType(ContentType.Application.Json)
54 setBody(UpdateSessionRequest(title = title))
57 suspend fun deleteSession(id: String) {
58 client.delete("session/$id")
61 suspend fun listMessages(sessionId: String): List<MessageWithParts> =
62 client.get("session/$sessionId/message").body()
64 suspend fun sendPrompt(
67 model: ModelRef? = null,
68 agent: String? = null,
70 client.post("session/$sessionId/message") {
71 contentType(ContentType.Application.Json)
74 parts = listOf(PromptPart(text = text)),
81 suspend fun abort(sessionId: String) {
82 client.post("session/$sessionId/abort")
85 /** Invoke a slash-command by name via `POST /session/:id/command`. */
86 suspend fun runCommand(
89 arguments: String = "",
90 agent: String? = null,
92 client.post("session/$sessionId/command") {
93 contentType(ContentType.Application.Json)
94 setBody(CommandRequest(command = command, arguments = arguments, agent = agent))
97 suspend fun providers(): ProvidersResponse =
98 client.get("config/providers").body()
100 suspend fun agents(): List<Agent> =
101 client.get("agent").body()
103 suspend fun commands(): List<Command> =
104 client.get("command").body()
106 /** Respond to a permission request so a paused tool run can proceed. */
107 suspend fun respondPermission(
109 permissionId: String,
110 response: PermissionResponse,
112 client.post("session/$sessionId/permissions/$permissionId") {
113 contentType(ContentType.Application.Json)
114 setBody(PermissionReplyBody(response.wire))
120 suspend fun findFiles(query: String): List<String> =
121 client.get("find/file") { parameter("query", query) }.body()
123 suspend fun listDirectory(path: String): List<FileNode> =
124 client.get("file") { parameter("path", path) }.body()
126 suspend fun readFile(path: String): FileContent =
127 client.get("file/content") { parameter("path", path) }.body()
129 suspend fun fileStatus(): List<FileStatusEntry> =
130 client.get("file/status").body()
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list