feat(core): session.pending.list API with pending-only session_pending storage (#36126)
This commit is contained in:
parent
99156c10e6
commit
a72992e00f
43 changed files with 986 additions and 649 deletions
|
|
@ -226,64 +226,69 @@ export type Endpoint5_20Input = { readonly sessionID: Endpoint5_20Request["param
|
|||
export type Endpoint5_20Output = EffectValue<ReturnType<RawClient["server.session"]["session.context"]>>["data"]
|
||||
export type SessionContextOperation<E = never> = (input: Endpoint5_20Input) => Effect.Effect<Endpoint5_20Output, E>
|
||||
|
||||
type Endpoint5_21Request = Parameters<RawClient["server.session"]["session.instructions.entry.list"]>[0]
|
||||
type Endpoint5_21Request = Parameters<RawClient["server.session"]["session.pending.list"]>[0]
|
||||
export type Endpoint5_21Input = { readonly sessionID: Endpoint5_21Request["params"]["sessionID"] }
|
||||
export type Endpoint5_21Output = EffectValue<
|
||||
export type Endpoint5_21Output = EffectValue<ReturnType<RawClient["server.session"]["session.pending.list"]>>["data"]
|
||||
export type SessionPendingListOperation<E = never> = (input: Endpoint5_21Input) => Effect.Effect<Endpoint5_21Output, E>
|
||||
|
||||
type Endpoint5_22Request = Parameters<RawClient["server.session"]["session.instructions.entry.list"]>[0]
|
||||
export type Endpoint5_22Input = { readonly sessionID: Endpoint5_22Request["params"]["sessionID"] }
|
||||
export type Endpoint5_22Output = EffectValue<
|
||||
ReturnType<RawClient["server.session"]["session.instructions.entry.list"]>
|
||||
>["data"]
|
||||
export type SessionInstructionsEntryListOperation<E = never> = (
|
||||
input: Endpoint5_21Input,
|
||||
) => Effect.Effect<Endpoint5_21Output, E>
|
||||
|
||||
type Endpoint5_22Request = Parameters<RawClient["server.session"]["session.instructions.entry.put"]>[0]
|
||||
export type Endpoint5_22Input = {
|
||||
readonly sessionID: Endpoint5_22Request["params"]["sessionID"]
|
||||
readonly key: Endpoint5_22Request["params"]["key"]
|
||||
readonly value: Endpoint5_22Request["payload"]["value"]
|
||||
}
|
||||
export type Endpoint5_22Output = EffectValue<ReturnType<RawClient["server.session"]["session.instructions.entry.put"]>>
|
||||
export type SessionInstructionsEntryPutOperation<E = never> = (
|
||||
input: Endpoint5_22Input,
|
||||
) => Effect.Effect<Endpoint5_22Output, E>
|
||||
|
||||
type Endpoint5_23Request = Parameters<RawClient["server.session"]["session.instructions.entry.remove"]>[0]
|
||||
type Endpoint5_23Request = Parameters<RawClient["server.session"]["session.instructions.entry.put"]>[0]
|
||||
export type Endpoint5_23Input = {
|
||||
readonly sessionID: Endpoint5_23Request["params"]["sessionID"]
|
||||
readonly key: Endpoint5_23Request["params"]["key"]
|
||||
readonly value: Endpoint5_23Request["payload"]["value"]
|
||||
}
|
||||
export type Endpoint5_23Output = EffectValue<
|
||||
ReturnType<RawClient["server.session"]["session.instructions.entry.remove"]>
|
||||
>
|
||||
export type SessionInstructionsEntryRemoveOperation<E = never> = (
|
||||
export type Endpoint5_23Output = EffectValue<ReturnType<RawClient["server.session"]["session.instructions.entry.put"]>>
|
||||
export type SessionInstructionsEntryPutOperation<E = never> = (
|
||||
input: Endpoint5_23Input,
|
||||
) => Effect.Effect<Endpoint5_23Output, E>
|
||||
|
||||
type Endpoint5_24Request = Parameters<RawClient["server.session"]["session.log"]>[0]
|
||||
type Endpoint5_24Request = Parameters<RawClient["server.session"]["session.instructions.entry.remove"]>[0]
|
||||
export type Endpoint5_24Input = {
|
||||
readonly sessionID: Endpoint5_24Request["params"]["sessionID"]
|
||||
readonly after?: Endpoint5_24Request["query"]["after"]
|
||||
readonly follow?: Endpoint5_24Request["query"]["follow"]
|
||||
readonly key: Endpoint5_24Request["params"]["key"]
|
||||
}
|
||||
export type Endpoint5_24Output = StreamValue<EffectValue<ReturnType<RawClient["server.session"]["session.log"]>>>
|
||||
export type SessionLogOperation<E = never> = (input: Endpoint5_24Input) => Stream.Stream<Endpoint5_24Output, E>
|
||||
export type Endpoint5_24Output = EffectValue<
|
||||
ReturnType<RawClient["server.session"]["session.instructions.entry.remove"]>
|
||||
>
|
||||
export type SessionInstructionsEntryRemoveOperation<E = never> = (
|
||||
input: Endpoint5_24Input,
|
||||
) => Effect.Effect<Endpoint5_24Output, E>
|
||||
|
||||
type Endpoint5_25Request = Parameters<RawClient["server.session"]["session.interrupt"]>[0]
|
||||
export type Endpoint5_25Input = { readonly sessionID: Endpoint5_25Request["params"]["sessionID"] }
|
||||
export type Endpoint5_25Output = EffectValue<ReturnType<RawClient["server.session"]["session.interrupt"]>>
|
||||
export type SessionInterruptOperation<E = never> = (input: Endpoint5_25Input) => Effect.Effect<Endpoint5_25Output, E>
|
||||
type Endpoint5_25Request = Parameters<RawClient["server.session"]["session.log"]>[0]
|
||||
export type Endpoint5_25Input = {
|
||||
readonly sessionID: Endpoint5_25Request["params"]["sessionID"]
|
||||
readonly after?: Endpoint5_25Request["query"]["after"]
|
||||
readonly follow?: Endpoint5_25Request["query"]["follow"]
|
||||
}
|
||||
export type Endpoint5_25Output = StreamValue<EffectValue<ReturnType<RawClient["server.session"]["session.log"]>>>
|
||||
export type SessionLogOperation<E = never> = (input: Endpoint5_25Input) => Stream.Stream<Endpoint5_25Output, E>
|
||||
|
||||
type Endpoint5_26Request = Parameters<RawClient["server.session"]["session.background"]>[0]
|
||||
type Endpoint5_26Request = Parameters<RawClient["server.session"]["session.interrupt"]>[0]
|
||||
export type Endpoint5_26Input = { readonly sessionID: Endpoint5_26Request["params"]["sessionID"] }
|
||||
export type Endpoint5_26Output = EffectValue<ReturnType<RawClient["server.session"]["session.background"]>>
|
||||
export type SessionBackgroundOperation<E = never> = (input: Endpoint5_26Input) => Effect.Effect<Endpoint5_26Output, E>
|
||||
export type Endpoint5_26Output = EffectValue<ReturnType<RawClient["server.session"]["session.interrupt"]>>
|
||||
export type SessionInterruptOperation<E = never> = (input: Endpoint5_26Input) => Effect.Effect<Endpoint5_26Output, E>
|
||||
|
||||
type Endpoint5_27Request = Parameters<RawClient["server.session"]["session.message"]>[0]
|
||||
export type Endpoint5_27Input = {
|
||||
readonly sessionID: Endpoint5_27Request["params"]["sessionID"]
|
||||
readonly messageID: Endpoint5_27Request["params"]["messageID"]
|
||||
type Endpoint5_27Request = Parameters<RawClient["server.session"]["session.background"]>[0]
|
||||
export type Endpoint5_27Input = { readonly sessionID: Endpoint5_27Request["params"]["sessionID"] }
|
||||
export type Endpoint5_27Output = EffectValue<ReturnType<RawClient["server.session"]["session.background"]>>
|
||||
export type SessionBackgroundOperation<E = never> = (input: Endpoint5_27Input) => Effect.Effect<Endpoint5_27Output, E>
|
||||
|
||||
type Endpoint5_28Request = Parameters<RawClient["server.session"]["session.message"]>[0]
|
||||
export type Endpoint5_28Input = {
|
||||
readonly sessionID: Endpoint5_28Request["params"]["sessionID"]
|
||||
readonly messageID: Endpoint5_28Request["params"]["messageID"]
|
||||
}
|
||||
export type Endpoint5_27Output = EffectValue<ReturnType<RawClient["server.session"]["session.message"]>>["data"]
|
||||
export type SessionMessageOperation<E = never> = (input: Endpoint5_27Input) => Effect.Effect<Endpoint5_27Output, E>
|
||||
export type Endpoint5_28Output = EffectValue<ReturnType<RawClient["server.session"]["session.message"]>>["data"]
|
||||
export type SessionMessageOperation<E = never> = (input: Endpoint5_28Input) => Effect.Effect<Endpoint5_28Output, E>
|
||||
|
||||
export interface SessionApi<E = never> {
|
||||
readonly list: SessionListOperation<E>
|
||||
|
|
@ -309,6 +314,7 @@ export interface SessionApi<E = never> {
|
|||
readonly commit: SessionRevertCommitOperation<E>
|
||||
}
|
||||
readonly context: SessionContextOperation<E>
|
||||
readonly pending: { readonly list: SessionPendingListOperation<E> }
|
||||
readonly instructions: {
|
||||
readonly entry: {
|
||||
readonly list: SessionInstructionsEntryListOperation<E>
|
||||
|
|
|
|||
|
|
@ -318,43 +318,51 @@ const Endpoint5_20 = (raw: RawClient["server.session"]) => (input: Endpoint5_20I
|
|||
Effect.map((value) => value.data),
|
||||
)
|
||||
|
||||
type Endpoint5_21Request = Parameters<RawClient["server.session"]["session.instructions.entry.list"]>[0]
|
||||
type Endpoint5_21Request = Parameters<RawClient["server.session"]["session.pending.list"]>[0]
|
||||
type Endpoint5_21Input = { readonly sessionID: Endpoint5_21Request["params"]["sessionID"] }
|
||||
const Endpoint5_21 = (raw: RawClient["server.session"]) => (input: Endpoint5_21Input) =>
|
||||
raw["session.pending.list"]({ params: { sessionID: input["sessionID"] } }).pipe(
|
||||
Effect.mapError(mapClientError),
|
||||
Effect.map((value) => value.data),
|
||||
)
|
||||
|
||||
type Endpoint5_22Request = Parameters<RawClient["server.session"]["session.instructions.entry.list"]>[0]
|
||||
type Endpoint5_22Input = { readonly sessionID: Endpoint5_22Request["params"]["sessionID"] }
|
||||
const Endpoint5_22 = (raw: RawClient["server.session"]) => (input: Endpoint5_22Input) =>
|
||||
raw["session.instructions.entry.list"]({ params: { sessionID: input["sessionID"] } }).pipe(
|
||||
Effect.mapError(mapClientError),
|
||||
Effect.map((value) => value.data),
|
||||
)
|
||||
|
||||
type Endpoint5_22Request = Parameters<RawClient["server.session"]["session.instructions.entry.put"]>[0]
|
||||
type Endpoint5_22Input = {
|
||||
readonly sessionID: Endpoint5_22Request["params"]["sessionID"]
|
||||
readonly key: Endpoint5_22Request["params"]["key"]
|
||||
readonly value: Endpoint5_22Request["payload"]["value"]
|
||||
type Endpoint5_23Request = Parameters<RawClient["server.session"]["session.instructions.entry.put"]>[0]
|
||||
type Endpoint5_23Input = {
|
||||
readonly sessionID: Endpoint5_23Request["params"]["sessionID"]
|
||||
readonly key: Endpoint5_23Request["params"]["key"]
|
||||
readonly value: Endpoint5_23Request["payload"]["value"]
|
||||
}
|
||||
const Endpoint5_22 = (raw: RawClient["server.session"]) => (input: Endpoint5_22Input) =>
|
||||
const Endpoint5_23 = (raw: RawClient["server.session"]) => (input: Endpoint5_23Input) =>
|
||||
raw["session.instructions.entry.put"]({
|
||||
params: { sessionID: input["sessionID"], key: input["key"] },
|
||||
payload: { value: input["value"] },
|
||||
}).pipe(Effect.mapError(mapClientError))
|
||||
|
||||
type Endpoint5_23Request = Parameters<RawClient["server.session"]["session.instructions.entry.remove"]>[0]
|
||||
type Endpoint5_23Input = {
|
||||
readonly sessionID: Endpoint5_23Request["params"]["sessionID"]
|
||||
readonly key: Endpoint5_23Request["params"]["key"]
|
||||
type Endpoint5_24Request = Parameters<RawClient["server.session"]["session.instructions.entry.remove"]>[0]
|
||||
type Endpoint5_24Input = {
|
||||
readonly sessionID: Endpoint5_24Request["params"]["sessionID"]
|
||||
readonly key: Endpoint5_24Request["params"]["key"]
|
||||
}
|
||||
const Endpoint5_23 = (raw: RawClient["server.session"]) => (input: Endpoint5_23Input) =>
|
||||
const Endpoint5_24 = (raw: RawClient["server.session"]) => (input: Endpoint5_24Input) =>
|
||||
raw["session.instructions.entry.remove"]({ params: { sessionID: input["sessionID"], key: input["key"] } }).pipe(
|
||||
Effect.mapError(mapClientError),
|
||||
)
|
||||
|
||||
type Endpoint5_24Request = Parameters<RawClient["server.session"]["session.log"]>[0]
|
||||
type Endpoint5_24Input = {
|
||||
readonly sessionID: Endpoint5_24Request["params"]["sessionID"]
|
||||
readonly after?: Endpoint5_24Request["query"]["after"]
|
||||
readonly follow?: Endpoint5_24Request["query"]["follow"]
|
||||
type Endpoint5_25Request = Parameters<RawClient["server.session"]["session.log"]>[0]
|
||||
type Endpoint5_25Input = {
|
||||
readonly sessionID: Endpoint5_25Request["params"]["sessionID"]
|
||||
readonly after?: Endpoint5_25Request["query"]["after"]
|
||||
readonly follow?: Endpoint5_25Request["query"]["follow"]
|
||||
}
|
||||
const Endpoint5_24 = (raw: RawClient["server.session"]) => (input: Endpoint5_24Input) =>
|
||||
const Endpoint5_25 = (raw: RawClient["server.session"]) => (input: Endpoint5_25Input) =>
|
||||
Stream.unwrap(
|
||||
raw["session.log"]({
|
||||
params: { sessionID: input["sessionID"] },
|
||||
|
|
@ -365,22 +373,22 @@ const Endpoint5_24 = (raw: RawClient["server.session"]) => (input: Endpoint5_24I
|
|||
),
|
||||
)
|
||||
|
||||
type Endpoint5_25Request = Parameters<RawClient["server.session"]["session.interrupt"]>[0]
|
||||
type Endpoint5_25Input = { readonly sessionID: Endpoint5_25Request["params"]["sessionID"] }
|
||||
const Endpoint5_25 = (raw: RawClient["server.session"]) => (input: Endpoint5_25Input) =>
|
||||
raw["session.interrupt"]({ params: { sessionID: input["sessionID"] } }).pipe(Effect.mapError(mapClientError))
|
||||
|
||||
type Endpoint5_26Request = Parameters<RawClient["server.session"]["session.background"]>[0]
|
||||
type Endpoint5_26Request = Parameters<RawClient["server.session"]["session.interrupt"]>[0]
|
||||
type Endpoint5_26Input = { readonly sessionID: Endpoint5_26Request["params"]["sessionID"] }
|
||||
const Endpoint5_26 = (raw: RawClient["server.session"]) => (input: Endpoint5_26Input) =>
|
||||
raw["session.interrupt"]({ params: { sessionID: input["sessionID"] } }).pipe(Effect.mapError(mapClientError))
|
||||
|
||||
type Endpoint5_27Request = Parameters<RawClient["server.session"]["session.background"]>[0]
|
||||
type Endpoint5_27Input = { readonly sessionID: Endpoint5_27Request["params"]["sessionID"] }
|
||||
const Endpoint5_27 = (raw: RawClient["server.session"]) => (input: Endpoint5_27Input) =>
|
||||
raw["session.background"]({ params: { sessionID: input["sessionID"] } }).pipe(Effect.mapError(mapClientError))
|
||||
|
||||
type Endpoint5_27Request = Parameters<RawClient["server.session"]["session.message"]>[0]
|
||||
type Endpoint5_27Input = {
|
||||
readonly sessionID: Endpoint5_27Request["params"]["sessionID"]
|
||||
readonly messageID: Endpoint5_27Request["params"]["messageID"]
|
||||
type Endpoint5_28Request = Parameters<RawClient["server.session"]["session.message"]>[0]
|
||||
type Endpoint5_28Input = {
|
||||
readonly sessionID: Endpoint5_28Request["params"]["sessionID"]
|
||||
readonly messageID: Endpoint5_28Request["params"]["messageID"]
|
||||
}
|
||||
const Endpoint5_27 = (raw: RawClient["server.session"]) => (input: Endpoint5_27Input) =>
|
||||
const Endpoint5_28 = (raw: RawClient["server.session"]) => (input: Endpoint5_28Input) =>
|
||||
raw["session.message"]({ params: { sessionID: input["sessionID"], messageID: input["messageID"] } }).pipe(
|
||||
Effect.mapError(mapClientError),
|
||||
Effect.map((value) => value.data),
|
||||
|
|
@ -406,11 +414,12 @@ const adaptGroup5 = (raw: RawClient["server.session"]) => ({
|
|||
wait: Endpoint5_16(raw),
|
||||
revert: { stage: Endpoint5_17(raw), clear: Endpoint5_18(raw), commit: Endpoint5_19(raw) },
|
||||
context: Endpoint5_20(raw),
|
||||
instructions: { entry: { list: Endpoint5_21(raw), put: Endpoint5_22(raw), remove: Endpoint5_23(raw) } },
|
||||
log: Endpoint5_24(raw),
|
||||
interrupt: Endpoint5_25(raw),
|
||||
background: Endpoint5_26(raw),
|
||||
message: Endpoint5_27(raw),
|
||||
pending: { list: Endpoint5_21(raw) },
|
||||
instructions: { entry: { list: Endpoint5_22(raw), put: Endpoint5_23(raw), remove: Endpoint5_24(raw) } },
|
||||
log: Endpoint5_25(raw),
|
||||
interrupt: Endpoint5_26(raw),
|
||||
background: Endpoint5_27(raw),
|
||||
message: Endpoint5_28(raw),
|
||||
})
|
||||
|
||||
type Endpoint6_0Request = Parameters<RawClient["server.message"]["session.messages"]>[0]
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ export { Question } from "@opencode-ai/schema/question"
|
|||
export { Reference } from "@opencode-ai/schema/reference"
|
||||
export { AbsolutePath, RelativePath } from "@opencode-ai/schema/schema"
|
||||
export { Session } from "@opencode-ai/schema/session"
|
||||
export { SessionInput } from "@opencode-ai/schema/session-input"
|
||||
export { SessionPending } from "@opencode-ai/schema/session-pending"
|
||||
export { SessionMessage } from "@opencode-ai/schema/session-message"
|
||||
export { Skill } from "@opencode-ai/schema/skill"
|
||||
export { Prompt } from "@opencode-ai/schema/prompt"
|
||||
|
|
|
|||
|
|
@ -48,6 +48,8 @@ import type {
|
|||
SessionRevertCommitOutput,
|
||||
SessionContextInput,
|
||||
SessionContextOutput,
|
||||
SessionPendingListInput,
|
||||
SessionPendingListOutput,
|
||||
SessionInstructionsEntryListInput,
|
||||
SessionInstructionsEntryListOutput,
|
||||
SessionInstructionsEntryPutInput,
|
||||
|
|
@ -666,6 +668,19 @@ export function make(options: ClientOptions) {
|
|||
},
|
||||
requestOptions,
|
||||
).then((value) => value.data),
|
||||
pending: {
|
||||
list: (input: SessionPendingListInput, requestOptions?: RequestOptions) =>
|
||||
request<{ readonly data: SessionPendingListOutput }>(
|
||||
{
|
||||
method: "GET",
|
||||
path: `/api/session/${encodeURIComponent(input.sessionID)}/pending`,
|
||||
successStatus: 200,
|
||||
declaredStatuses: [404, 400, 401],
|
||||
empty: false,
|
||||
},
|
||||
requestOptions,
|
||||
).then((value) => value.data),
|
||||
},
|
||||
instructions: {
|
||||
entry: {
|
||||
list: (input: SessionInstructionsEntryListInput, requestOptions?: RequestOptions) =>
|
||||
|
|
|
|||
|
|
@ -624,7 +624,6 @@ export type SessionPromptOutput = {
|
|||
id: string
|
||||
sessionID: string
|
||||
timeCreated: number
|
||||
promotedSeq?: number
|
||||
type: "user"
|
||||
data: {
|
||||
text: string
|
||||
|
|
@ -824,7 +823,6 @@ export type SessionCommandOutput = {
|
|||
id: string
|
||||
sessionID: string
|
||||
timeCreated: number
|
||||
promotedSeq?: number
|
||||
type: "user"
|
||||
data: {
|
||||
text: string
|
||||
|
|
@ -922,7 +920,6 @@ export type SessionSyntheticOutput = {
|
|||
id: string
|
||||
sessionID: string
|
||||
timeCreated: number
|
||||
promotedSeq?: number
|
||||
type: "synthetic"
|
||||
data: { text: string; description?: string; metadata?: { [x: string]: JsonValue } }
|
||||
delivery: "steer" | "queue"
|
||||
|
|
@ -943,14 +940,7 @@ export type SessionCompactInput = {
|
|||
}
|
||||
|
||||
export type SessionCompactOutput = {
|
||||
data: {
|
||||
admittedSeq: number
|
||||
id: string
|
||||
sessionID: string
|
||||
timeCreated: number
|
||||
type: "compaction"
|
||||
handledSeq?: number
|
||||
}
|
||||
data: { admittedSeq: number; id: string; sessionID: string; timeCreated: number; type: "compaction" }
|
||||
}["data"]
|
||||
|
||||
export type SessionWaitInput = { readonly sessionID: { readonly sessionID: string }["sessionID"] }
|
||||
|
|
@ -1145,6 +1135,44 @@ export type SessionContextOutput = {
|
|||
>
|
||||
}["data"]
|
||||
|
||||
export type SessionPendingListInput = { readonly sessionID: { readonly sessionID: string }["sessionID"] }
|
||||
|
||||
export type SessionPendingListOutput = {
|
||||
data: Array<
|
||||
| {
|
||||
admittedSeq: number
|
||||
id: string
|
||||
sessionID: string
|
||||
timeCreated: number
|
||||
type: "user"
|
||||
data: {
|
||||
text: string
|
||||
files?: Array<{
|
||||
data: string
|
||||
mime: string
|
||||
source: { type: "inline" } | { type: "uri"; uri: string }
|
||||
name?: string
|
||||
description?: string
|
||||
mention?: { start: number; end: number; text: string }
|
||||
}>
|
||||
agents?: Array<{ name: string; mention?: { start: number; end: number; text: string } }>
|
||||
metadata?: { [x: string]: JsonValue }
|
||||
}
|
||||
delivery: "steer" | "queue"
|
||||
}
|
||||
| {
|
||||
admittedSeq: number
|
||||
id: string
|
||||
sessionID: string
|
||||
timeCreated: number
|
||||
type: "synthetic"
|
||||
data: { text: string; description?: string; metadata?: { [x: string]: JsonValue } }
|
||||
delivery: "steer" | "queue"
|
||||
}
|
||||
| { admittedSeq: number; id: string; sessionID: string; timeCreated: number; type: "compaction" }
|
||||
>
|
||||
}["data"]
|
||||
|
||||
export type SessionInstructionsEntryListInput = { readonly sessionID: { readonly sessionID: string }["sessionID"] }
|
||||
|
||||
export type SessionInstructionsEntryListOutput = { data: Array<{ key: string; value: JsonValue }> }["data"]
|
||||
|
|
|
|||
|
|
@ -1,25 +1,10 @@
|
|||
import { expect, test } from "bun:test"
|
||||
import { Schema } from "effect"
|
||||
import { AgentV2 } from "@opencode-ai/core/agent"
|
||||
import { Location as CoreLocation } from "@opencode-ai/core/location"
|
||||
import { ModelV2 } from "@opencode-ai/core/model"
|
||||
import { ProjectV2 } from "@opencode-ai/core/project"
|
||||
import { SessionV2 } from "@opencode-ai/core/session"
|
||||
import { SessionInput as CoreSessionInput } from "@opencode-ai/core/session/input"
|
||||
import { SessionMessage as CoreSessionMessage } from "@opencode-ai/core/session/message"
|
||||
import { Agent } from "@opencode-ai/schema/agent"
|
||||
import { Location } from "@opencode-ai/schema/location"
|
||||
import { Model } from "@opencode-ai/schema/model"
|
||||
import { Project } from "@opencode-ai/schema/project"
|
||||
import { Provider } from "@opencode-ai/schema/provider"
|
||||
import { Prompt } from "@opencode-ai/schema/prompt"
|
||||
import { Session } from "@opencode-ai/schema/session"
|
||||
import { SessionInput } from "@opencode-ai/schema/session-input"
|
||||
import { SessionMessage } from "@opencode-ai/schema/session-message"
|
||||
import { Workspace } from "@opencode-ai/schema/workspace"
|
||||
import { Api } from "@opencode-ai/server/api"
|
||||
import { compile, emitPromise } from "@opencode-ai/httpapi-codegen"
|
||||
import { ClientApi, groupNames, promiseOmitEndpoints } from "../src/contract"
|
||||
|
||||
const Client = await import("../src/effect")
|
||||
|
||||
|
|
@ -29,34 +14,6 @@ test("effect entrypoint exposes canonical Schema contracts", () => {
|
|||
expect(Client.Session).toBe(Session)
|
||||
})
|
||||
|
||||
test("Core and Server reuse the authoritative Schema and Protocol values", () => {
|
||||
expect(AgentV2.ID).toBe(Agent.ID)
|
||||
expect(CoreLocation.Ref).toBe(Location.Ref)
|
||||
expect(ModelV2.Ref).toBe(Model.Ref)
|
||||
expect(SessionV2.Info).toBe(Session.Info)
|
||||
expect(ProjectV2.Current).toBe(Project.Current)
|
||||
expect(ProjectV2.Directory).toBe(Project.Directory)
|
||||
expect(ProjectV2.Directories).toBe(Project.Directories)
|
||||
expect(CoreSessionInput.Message).toBe(SessionInput.Message)
|
||||
expect(CoreSessionInput.User).toBe(SessionInput.User)
|
||||
expect(CoreSessionInput.Synthetic).toBe(SessionInput.Synthetic)
|
||||
expect(CoreSessionMessage.Info).toBe(SessionMessage.Info)
|
||||
expect(Api.groups["server.session"].identifier).toBe("server.session")
|
||||
expect(Api.groups["server.project"].identifier).toBe("server.project")
|
||||
expect(Object.keys(ClientApi.groups)).toEqual(Object.keys(Api.groups))
|
||||
expect(Session.ID.create()).toStartWith("ses_")
|
||||
expect(Project.ID.global).toBe("global")
|
||||
expect(Provider.ID.anthropic).toBe("anthropic")
|
||||
expect(Workspace.ID.create()).toStartWith("wrk_")
|
||||
})
|
||||
|
||||
test("client and Server contracts generate identically", () => {
|
||||
const server = compile(Api, { groupNames, omitEndpoints: promiseOmitEndpoints })
|
||||
const client = compile(ClientApi, { groupNames, omitEndpoints: promiseOmitEndpoints })
|
||||
|
||||
expect(emitPromise(client)).toEqual(emitPromise(server))
|
||||
})
|
||||
|
||||
test("shared DTO schemas construct and decode plain objects", () => {
|
||||
const made = Prompt.make({ text: "hello" })
|
||||
const decoded = Schema.decodeUnknownSync(Prompt)({ text: "hello" })
|
||||
|
|
@ -67,5 +24,4 @@ test("shared DTO schemas construct and decode plain objects", () => {
|
|||
expect(Object.getPrototypeOf(content)).toBe(Object.prototype)
|
||||
expect(Prompt.ast.annotations?.identifier).toBe("Prompt")
|
||||
expect(SessionMessage.AssistantText.ast.annotations?.identifier).toBe("Session.Message.Assistant.Text")
|
||||
expect(CoreSessionMessage.AssistantText).toBe(SessionMessage.AssistantText)
|
||||
})
|
||||
|
|
|
|||
|
|
@ -227,6 +227,34 @@ test("session instructions methods use the public HTTP contract", async () => {
|
|||
])
|
||||
})
|
||||
|
||||
test("session.pending.list uses the public HTTP contract", async () => {
|
||||
const requests: Array<{ method: string; url: string }> = []
|
||||
const pending = [
|
||||
{
|
||||
admittedSeq: 3,
|
||||
id: "msg_pending",
|
||||
sessionID: "ses_test",
|
||||
timeCreated: 1_717_171_717_000,
|
||||
type: "user",
|
||||
data: { text: "Fix the failing tests" },
|
||||
delivery: "steer",
|
||||
},
|
||||
]
|
||||
const client = OpenCode.make({
|
||||
baseUrl: "http://localhost:3000",
|
||||
fetch: async (input, init) => {
|
||||
const request = input instanceof Request ? input : new Request(input, init)
|
||||
requests.push({ method: request.method, url: request.url })
|
||||
return Response.json({ data: pending })
|
||||
},
|
||||
})
|
||||
|
||||
const result = await client.session.pending.list({ sessionID: "ses_test" })
|
||||
|
||||
expect(result).toEqual(pending)
|
||||
expect(requests).toEqual([{ method: "GET", url: "http://localhost:3000/api/session/ses_test/pending" }])
|
||||
})
|
||||
|
||||
test("event.subscribe exposes the Promise event stream wire projection", async () => {
|
||||
const client = OpenCode.make({
|
||||
baseUrl: "http://localhost:3000",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue