feat(sdk): add HttpApi clients and embedded host (#33445)
This commit is contained in:
parent
c45d1db9a0
commit
cdd67cf30f
59 changed files with 4629 additions and 316 deletions
|
|
@ -1,6 +0,0 @@
|
|||
export * as Agent from "./agent"
|
||||
|
||||
import { AgentV2 } from "../agent"
|
||||
|
||||
export const ID = AgentV2.ID
|
||||
export type ID = AgentV2.ID
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
/** Intentional supported native API. Other core subpaths remain internal implementation surfaces. */
|
||||
export { Agent } from "./agent"
|
||||
export { Model } from "./model"
|
||||
export { OpenCode } from "./opencode"
|
||||
export { Session } from "./session"
|
||||
export { Tool } from "./tool"
|
||||
export { Location } from "./location"
|
||||
export { Prompt } from "../session/prompt"
|
||||
export { AbsolutePath } from "../schema"
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
export * as Location from "./location"
|
||||
|
||||
import { Location } from "../location"
|
||||
|
||||
export const Ref = Location.Ref
|
||||
export type Ref = Location.Ref
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
export * as Model from "./model"
|
||||
|
||||
import { ModelV2 } from "../model"
|
||||
|
||||
export const ID = ModelV2.ID
|
||||
export type ID = ModelV2.ID
|
||||
|
||||
export const Ref = ModelV2.Ref
|
||||
export type Ref = ModelV2.Ref
|
||||
|
|
@ -1,76 +0,0 @@
|
|||
export * as OpenCode from "./opencode"
|
||||
|
||||
import { Context, Effect, Layer } from "effect"
|
||||
import { Database } from "../database/database"
|
||||
import { EventV2 } from "../event"
|
||||
import { LocationServiceMap } from "../location-layer"
|
||||
import { ProjectV2 } from "../project"
|
||||
import { SessionV2 } from "../session"
|
||||
import * as SessionExecutionLocal from "../session/execution/local"
|
||||
import { SessionProjector } from "../session/projector"
|
||||
import { SessionStore } from "../session/store"
|
||||
import { ApplicationTools } from "../tool/application-tools"
|
||||
import { Session } from "./session"
|
||||
import { Tool } from "./tool"
|
||||
|
||||
export interface Interface {
|
||||
readonly sessions: Session.Interface
|
||||
readonly tools: Tool.Interface
|
||||
}
|
||||
|
||||
/** Intentional public native API for Effect applications embedding OpenCode. */
|
||||
export class Service extends Context.Service<Service, Interface>()("@opencode/public/OpenCode") {}
|
||||
|
||||
const SessionsLayer = SessionV2.layer.pipe(
|
||||
Layer.provide(SessionProjector.layer),
|
||||
Layer.provide(SessionExecutionLocal.layer),
|
||||
Layer.provide(SessionStore.layer),
|
||||
Layer.provide(EventV2.layer),
|
||||
Layer.provide(Database.defaultLayer),
|
||||
Layer.provide(ProjectV2.defaultLayer),
|
||||
Layer.provide(LocationServiceMap.layer.pipe(Layer.provide(ApplicationTools.layer))),
|
||||
Layer.orDie,
|
||||
)
|
||||
// TODO: Accept explicit storage so tests and embeddings can select disposable or application-owned persistence.
|
||||
export const layer = Layer.effect(
|
||||
Service,
|
||||
Effect.gen(function* () {
|
||||
const sessions = yield* SessionV2.Service
|
||||
const tools = yield* ApplicationTools.Service
|
||||
return Service.of({
|
||||
tools: { register: tools.register },
|
||||
sessions: {
|
||||
create: (input) =>
|
||||
sessions.create({
|
||||
id: input.id,
|
||||
agent: input.agent,
|
||||
model: input.model,
|
||||
location: input.location,
|
||||
}),
|
||||
get: sessions.get,
|
||||
list: sessions.list,
|
||||
switchModel: sessions.switchModel,
|
||||
interrupt: sessions.interrupt,
|
||||
prompt: (input) =>
|
||||
sessions.prompt({
|
||||
id: input.id,
|
||||
sessionID: input.sessionID,
|
||||
prompt: input.prompt,
|
||||
delivery: input.delivery,
|
||||
}),
|
||||
messages: (input) =>
|
||||
sessions.messages({
|
||||
sessionID: input.sessionID,
|
||||
limit: input.limit,
|
||||
order: input.order,
|
||||
cursor: input.cursor,
|
||||
}),
|
||||
message: (input) => sessions.message({ sessionID: input.sessionID, messageID: input.messageID }),
|
||||
context: sessions.context,
|
||||
events: (input) => sessions.events({ sessionID: input.sessionID, after: input.after }),
|
||||
},
|
||||
})
|
||||
}),
|
||||
).pipe(Layer.provide(Layer.merge(ApplicationTools.layer, SessionsLayer)))
|
||||
|
||||
// TODO: Add OpenCode.create(...) as the Promise facade over the same native API semantics.
|
||||
|
|
@ -1,96 +0,0 @@
|
|||
export * as Session from "./session"
|
||||
|
||||
import { Effect, Stream } from "effect"
|
||||
import { SessionV2 } from "../session"
|
||||
import { MessageDecodeError } from "../session/error"
|
||||
import { SessionEvent } from "../session/event"
|
||||
import { SessionInput } from "../session/input"
|
||||
import { SessionMessage } from "../session/message"
|
||||
import { Prompt } from "../session/prompt"
|
||||
import { Agent } from "./agent"
|
||||
import { Location } from "./location"
|
||||
import { Model } from "./model"
|
||||
|
||||
export const ID = SessionV2.ID
|
||||
export type ID = SessionV2.ID
|
||||
|
||||
export const Info = SessionV2.Info
|
||||
export type Info = SessionV2.Info
|
||||
|
||||
export const MessageID = SessionMessage.ID
|
||||
export type MessageID = SessionMessage.ID
|
||||
|
||||
export const Message = SessionMessage.Message
|
||||
export type Message = SessionMessage.Message
|
||||
|
||||
export const Admission = SessionInput.Admitted
|
||||
export type Admission = SessionInput.Admitted
|
||||
|
||||
export const Delivery = SessionInput.Delivery
|
||||
export type Delivery = SessionInput.Delivery
|
||||
|
||||
export const ListInput = SessionV2.ListInput
|
||||
export type ListInput = SessionV2.ListInput
|
||||
|
||||
export type Event = SessionEvent.DurableEvent
|
||||
|
||||
export const NotFoundError = SessionV2.NotFoundError
|
||||
export type NotFoundError = SessionV2.NotFoundError
|
||||
|
||||
export const PromptConflictError = SessionV2.PromptConflictError
|
||||
export type PromptConflictError = SessionV2.PromptConflictError
|
||||
|
||||
export { MessageDecodeError }
|
||||
|
||||
export interface CreateInput {
|
||||
readonly id?: ID
|
||||
readonly agent?: Agent.ID
|
||||
readonly model?: Model.Ref
|
||||
readonly location: Location.Ref
|
||||
}
|
||||
|
||||
export interface PromptInput {
|
||||
readonly id?: MessageID
|
||||
readonly sessionID: ID
|
||||
readonly prompt: Prompt
|
||||
readonly delivery?: Delivery
|
||||
}
|
||||
|
||||
export interface SwitchModelInput {
|
||||
readonly sessionID: ID
|
||||
readonly model: Model.Ref
|
||||
}
|
||||
|
||||
export interface MessagesInput {
|
||||
readonly sessionID: ID
|
||||
readonly limit?: number
|
||||
readonly order?: "asc" | "desc"
|
||||
readonly cursor?: {
|
||||
readonly id: MessageID
|
||||
readonly direction: "previous" | "next"
|
||||
}
|
||||
}
|
||||
|
||||
export interface MessageInput {
|
||||
readonly sessionID: ID
|
||||
readonly messageID: MessageID
|
||||
}
|
||||
|
||||
export interface EventsInput {
|
||||
readonly sessionID: ID
|
||||
readonly after?: number
|
||||
}
|
||||
|
||||
export interface Interface {
|
||||
readonly create: (input: CreateInput) => Effect.Effect<Info>
|
||||
readonly get: (sessionID: ID) => Effect.Effect<Info, NotFoundError>
|
||||
readonly list: (input?: ListInput) => Effect.Effect<Info[]>
|
||||
readonly prompt: (input: PromptInput) => Effect.Effect<Admission, NotFoundError | PromptConflictError>
|
||||
readonly switchModel: (input: SwitchModelInput) => Effect.Effect<void, NotFoundError>
|
||||
/** Interrupt the active V2 execution chain for one Session on this process. Interrupting an idle or missing Session is a no-op. */
|
||||
readonly interrupt: (sessionID: ID) => Effect.Effect<void>
|
||||
readonly messages: (input: MessagesInput) => Effect.Effect<Message[], NotFoundError | MessageDecodeError>
|
||||
readonly message: (input: MessageInput) => Effect.Effect<Message | undefined>
|
||||
readonly context: (sessionID: ID) => Effect.Effect<Message[], NotFoundError | MessageDecodeError>
|
||||
readonly events: (input: EventsInput) => Stream.Stream<Event, NotFoundError>
|
||||
}
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
export * as Tool from "./tool"
|
||||
|
||||
import { Effect, Scope } from "effect"
|
||||
import type { AnyTool, RegistrationError } from "../tool/tool"
|
||||
|
||||
export { Failure, RegistrationError, make } from "../tool/tool"
|
||||
export type { AnyTool, Content, Context, Definition } from "../tool/tool"
|
||||
|
||||
export interface Interface {
|
||||
/**
|
||||
* Register same-process tools on this OpenCode instance for the current Scope.
|
||||
* Location tools with the same name take precedence where they are installed.
|
||||
* Closing the Scope removes the tools immediately, so calls that have not
|
||||
* started settling may fail because the tool is no longer available.
|
||||
*/
|
||||
readonly register: (tools: Readonly<Record<string, AnyTool>>) => Effect.Effect<void, RegistrationError, Scope.Scope>
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue