Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ export const PermissionResponsePayload = Schema.Struct({
export const SessionPaths = {
list: root,
status: `${root}/status`,
getStatus: `${root}/:sessionID/status`,
get: `${root}/:sessionID`,
children: `${root}/:sessionID/children`,
todo: `${root}/:sessionID/todo`,
Expand Down Expand Up @@ -125,6 +126,18 @@ export const SessionApi = HttpApi.make("session")
description: "Retrieve the current status of all sessions, including active, idle, and completed states.",
}),
),
HttpApiEndpoint.get("getStatus", SessionPaths.getStatus, {
params: { sessionID: SessionID },
query: WorkspaceRoutingQuery,
success: described(SessionStatus.Info, "Get session status"),
error: HttpApiError.BadRequest,
}).annotateMerge(
OpenApi.annotations({
identifier: "session.getStatus",
summary: "Get session status",
description: "Retrieve the current runtime status for a specific OpenCode session.",
}),
),
HttpApiEndpoint.get("get", SessionPaths.get, {
params: { sessionID: SessionID },
query: WorkspaceRoutingQuery,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ export const sessionHandlers = HttpApiBuilder.group(InstanceHttpApi, "session",
return Object.fromEntries(yield* statusSvc.list())
})

const getStatus = Effect.fn("SessionHttpApi.getStatus")(function* (ctx: { params: { sessionID: SessionID } }) {
return yield* statusSvc.get(ctx.params.sessionID)
})

const requireSession = Effect.fn("SessionHttpApi.requireSession")(function* (sessionID: SessionID) {
return yield* SessionError.mapStorageNotFound(session.get(sessionID))
})
Expand Down Expand Up @@ -406,6 +410,7 @@ export const sessionHandlers = HttpApiBuilder.group(InstanceHttpApi, "session",
return handlers
.handle("list", list)
.handle("status", status)
.handle("getStatus", getStatus)
.handle("get", get)
.handle("children", children)
.handle("todo", todo)
Expand Down
11 changes: 11 additions & 0 deletions packages/opencode/test/server/httpapi-exercise/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -731,6 +731,17 @@ const scenarios: Scenario[] = [
.get("/session/status", "session.status")
.seeded((ctx) => ctx.session({ title: "Status session" }))
.json(200, object),
http.protected
.get("/session/{sessionID}/status", "session.getStatus")
.seeded((ctx) => ctx.session({ title: "Single status session" }))
.at((ctx) => ({
path: route("/session/{sessionID}/status", { sessionID: ctx.state.id }),
headers: ctx.headers(),
}))
.json(200, (body) => {
object(body)
check(isRecord(body) && body.type === "idle", "single session status should default to idle")
}),
http.protected
.post("/session", "session.create")
.mutating()
Expand Down
3 changes: 3 additions & 0 deletions packages/opencode/test/server/httpapi-session.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,9 @@ describe("session HttpApi", () => {
expect(Object.hasOwn(listed[0]!, "parentID")).toBe(false)

expect(yield* requestJson<Record<string, unknown>>(SessionPaths.status, { headers })).toEqual({})
const sessionStatus = yield* request(`/session/${parent.id}/status`, { headers })
expect(sessionStatus.status).toBe(200)
expect(yield* json<Record<string, unknown>>(sessionStatus)).toEqual({ type: "idle" })

expect(
yield* requestJson<Session.Info>(pathFor(SessionPaths.get, { sessionID: parent.id }), { headers }),
Expand Down
34 changes: 34 additions & 0 deletions packages/sdk/js/src/v2/gen/sdk.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,8 @@ import type {
SessionForkResponses,
SessionGetErrors,
SessionGetResponses,
SessionGetStatusErrors,
SessionGetStatusResponses,
SessionInitErrors,
SessionInitResponses,
SessionListErrors,
Expand Down Expand Up @@ -3160,6 +3162,38 @@ export class Session2 extends HeyApiClient {
})
}

/**
* Get session status
*
* Retrieve the current runtime status for a specific OpenCode session.
*/
public getStatus<ThrowOnError extends boolean = false>(
parameters: {
sessionID: string
directory?: string
workspace?: string
},
options?: Options<never, ThrowOnError>,
) {
const params = buildClientParams(
[parameters],
[
{
args: [
{ in: "path", key: "sessionID" },
{ in: "query", key: "directory" },
{ in: "query", key: "workspace" },
],
},
],
)
return (options?.client ?? this.client).get<SessionGetStatusResponses, SessionGetStatusErrors, ThrowOnError>({
url: "/session/{sessionID}/status",
...options,
...params,
})
}

/**
* Delete session
*
Expand Down
30 changes: 30 additions & 0 deletions packages/sdk/js/src/v2/gen/types.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6122,6 +6122,36 @@ export type SessionStatusResponses = {

export type SessionStatusResponse = SessionStatusResponses[keyof SessionStatusResponses]

export type SessionGetStatusData = {
body?: never
path: {
sessionID: string
}
query?: {
directory?: string
workspace?: string
}
url: "/session/{sessionID}/status"
}

export type SessionGetStatusErrors = {
/**
* BadRequest | InvalidRequestError
*/
400: EffectHttpApiErrorBadRequest | InvalidRequestError
}

export type SessionGetStatusError = SessionGetStatusErrors[keyof SessionGetStatusErrors]

export type SessionGetStatusResponses = {
/**
* Get session status
*/
200: SessionStatus
}

export type SessionGetStatusResponse = SessionGetStatusResponses[keyof SessionGetStatusResponses]

export type SessionDeleteData = {
body?: never
path: {
Expand Down
Loading