mirror of
https://github.com/anomalyco/opencode.git
synced 2026-07-31 07:26:47 -04:00
Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a6761d4fe0 | |||
| 305466e5ef | |||
| 704e9ff3fb | |||
| dbe7b937ef | |||
| 9de001d92f | |||
| 3cd894d40a | |||
| 0e705e2a05 | |||
| 421d649019 | |||
| a7855aa169 |
@@ -820,55 +820,71 @@ export interface EventApi<E = never> {
|
||||
readonly subscribe: EventSubscribeOperation<E>
|
||||
}
|
||||
|
||||
type Endpoint20_0Request = Parameters<RawClient["server.pty"]["pty.list"]>[0]
|
||||
type Endpoint20_0Request = Parameters<RawClient["server.pty"]["pty.shells"]>[0]
|
||||
export type Endpoint20_0Input = { readonly location?: Endpoint20_0Request["query"]["location"] }
|
||||
export type Endpoint20_0Output = EffectValue<ReturnType<RawClient["server.pty"]["pty.list"]>>
|
||||
export type PtyListOperation<E = never> = (input?: Endpoint20_0Input) => Effect.Effect<Endpoint20_0Output, E>
|
||||
export type Endpoint20_0Output = EffectValue<ReturnType<RawClient["server.pty"]["pty.shells"]>>
|
||||
export type PtyShellsOperation<E = never> = (input?: Endpoint20_0Input) => Effect.Effect<Endpoint20_0Output, E>
|
||||
|
||||
type Endpoint20_1Request = Parameters<RawClient["server.pty"]["pty.create"]>[0]
|
||||
export type Endpoint20_1Input = {
|
||||
readonly location?: Endpoint20_1Request["query"]["location"]
|
||||
readonly command?: Endpoint20_1Request["payload"]["command"]
|
||||
readonly args?: Endpoint20_1Request["payload"]["args"]
|
||||
readonly cwd?: Endpoint20_1Request["payload"]["cwd"]
|
||||
readonly title?: Endpoint20_1Request["payload"]["title"]
|
||||
readonly env?: Endpoint20_1Request["payload"]["env"]
|
||||
}
|
||||
export type Endpoint20_1Output = EffectValue<ReturnType<RawClient["server.pty"]["pty.create"]>>
|
||||
export type PtyCreateOperation<E = never> = (input?: Endpoint20_1Input) => Effect.Effect<Endpoint20_1Output, E>
|
||||
type Endpoint20_1Request = Parameters<RawClient["server.pty"]["pty.list"]>[0]
|
||||
export type Endpoint20_1Input = { readonly location?: Endpoint20_1Request["query"]["location"] }
|
||||
export type Endpoint20_1Output = EffectValue<ReturnType<RawClient["server.pty"]["pty.list"]>>
|
||||
export type PtyListOperation<E = never> = (input?: Endpoint20_1Input) => Effect.Effect<Endpoint20_1Output, E>
|
||||
|
||||
type Endpoint20_2Request = Parameters<RawClient["server.pty"]["pty.get"]>[0]
|
||||
type Endpoint20_2Request = Parameters<RawClient["server.pty"]["pty.create"]>[0]
|
||||
export type Endpoint20_2Input = {
|
||||
readonly ptyID: Endpoint20_2Request["params"]["ptyID"]
|
||||
readonly location?: Endpoint20_2Request["query"]["location"]
|
||||
readonly command?: Endpoint20_2Request["payload"]["command"]
|
||||
readonly args?: Endpoint20_2Request["payload"]["args"]
|
||||
readonly cwd?: Endpoint20_2Request["payload"]["cwd"]
|
||||
readonly title?: Endpoint20_2Request["payload"]["title"]
|
||||
readonly env?: Endpoint20_2Request["payload"]["env"]
|
||||
}
|
||||
export type Endpoint20_2Output = EffectValue<ReturnType<RawClient["server.pty"]["pty.get"]>>
|
||||
export type PtyGetOperation<E = never> = (input: Endpoint20_2Input) => Effect.Effect<Endpoint20_2Output, E>
|
||||
export type Endpoint20_2Output = EffectValue<ReturnType<RawClient["server.pty"]["pty.create"]>>
|
||||
export type PtyCreateOperation<E = never> = (input?: Endpoint20_2Input) => Effect.Effect<Endpoint20_2Output, E>
|
||||
|
||||
type Endpoint20_3Request = Parameters<RawClient["server.pty"]["pty.update"]>[0]
|
||||
type Endpoint20_3Request = Parameters<RawClient["server.pty"]["pty.get"]>[0]
|
||||
export type Endpoint20_3Input = {
|
||||
readonly ptyID: Endpoint20_3Request["params"]["ptyID"]
|
||||
readonly location?: Endpoint20_3Request["query"]["location"]
|
||||
readonly title?: Endpoint20_3Request["payload"]["title"]
|
||||
readonly size?: Endpoint20_3Request["payload"]["size"]
|
||||
}
|
||||
export type Endpoint20_3Output = EffectValue<ReturnType<RawClient["server.pty"]["pty.update"]>>
|
||||
export type PtyUpdateOperation<E = never> = (input: Endpoint20_3Input) => Effect.Effect<Endpoint20_3Output, E>
|
||||
export type Endpoint20_3Output = EffectValue<ReturnType<RawClient["server.pty"]["pty.get"]>>
|
||||
export type PtyGetOperation<E = never> = (input: Endpoint20_3Input) => Effect.Effect<Endpoint20_3Output, E>
|
||||
|
||||
type Endpoint20_4Request = Parameters<RawClient["server.pty"]["pty.remove"]>[0]
|
||||
type Endpoint20_4Request = Parameters<RawClient["server.pty"]["pty.update"]>[0]
|
||||
export type Endpoint20_4Input = {
|
||||
readonly ptyID: Endpoint20_4Request["params"]["ptyID"]
|
||||
readonly location?: Endpoint20_4Request["query"]["location"]
|
||||
readonly title?: Endpoint20_4Request["payload"]["title"]
|
||||
readonly size?: Endpoint20_4Request["payload"]["size"]
|
||||
}
|
||||
export type Endpoint20_4Output = EffectValue<ReturnType<RawClient["server.pty"]["pty.remove"]>>
|
||||
export type PtyRemoveOperation<E = never> = (input: Endpoint20_4Input) => Effect.Effect<Endpoint20_4Output, E>
|
||||
export type Endpoint20_4Output = EffectValue<ReturnType<RawClient["server.pty"]["pty.update"]>>
|
||||
export type PtyUpdateOperation<E = never> = (input: Endpoint20_4Input) => Effect.Effect<Endpoint20_4Output, E>
|
||||
|
||||
type Endpoint20_5Request = Parameters<RawClient["server.pty"]["pty.remove"]>[0]
|
||||
export type Endpoint20_5Input = {
|
||||
readonly ptyID: Endpoint20_5Request["params"]["ptyID"]
|
||||
readonly location?: Endpoint20_5Request["query"]["location"]
|
||||
}
|
||||
export type Endpoint20_5Output = EffectValue<ReturnType<RawClient["server.pty"]["pty.remove"]>>
|
||||
export type PtyRemoveOperation<E = never> = (input: Endpoint20_5Input) => Effect.Effect<Endpoint20_5Output, E>
|
||||
|
||||
type Endpoint20_6Request = Parameters<RawClient["server.pty"]["pty.connectToken"]>[0]
|
||||
export type Endpoint20_6Input = {
|
||||
readonly ptyID: Endpoint20_6Request["params"]["ptyID"]
|
||||
readonly location?: Endpoint20_6Request["query"]["location"]
|
||||
readonly "x-opencode-ticket"?: Endpoint20_6Request["headers"]["x-opencode-ticket"]
|
||||
}
|
||||
export type Endpoint20_6Output = EffectValue<ReturnType<RawClient["server.pty"]["pty.connectToken"]>>
|
||||
export type PtyConnectTokenOperation<E = never> = (input: Endpoint20_6Input) => Effect.Effect<Endpoint20_6Output, E>
|
||||
|
||||
export interface PtyApi<E = never> {
|
||||
readonly shells: PtyShellsOperation<E>
|
||||
readonly list: PtyListOperation<E>
|
||||
readonly create: PtyCreateOperation<E>
|
||||
readonly get: PtyGetOperation<E>
|
||||
readonly update: PtyUpdateOperation<E>
|
||||
readonly remove: PtyRemoveOperation<E>
|
||||
readonly connectToken: PtyConnectTokenOperation<E>
|
||||
}
|
||||
|
||||
type Endpoint21_0Request = Parameters<RawClient["server.shell"]["shell.list"]>[0]
|
||||
@@ -1011,32 +1027,47 @@ export interface ProjectCopyApi<E = never> {
|
||||
readonly refresh: ProjectCopyRefreshOperation<E>
|
||||
}
|
||||
|
||||
type Endpoint25_0Request = Parameters<RawClient["server.vcs"]["vcs.status"]>[0]
|
||||
type Endpoint25_0Request = Parameters<RawClient["server.vcs"]["vcs.get"]>[0]
|
||||
export type Endpoint25_0Input = { readonly location?: Endpoint25_0Request["query"]["location"] }
|
||||
export type Endpoint25_0Output = EffectValue<ReturnType<RawClient["server.vcs"]["vcs.status"]>>
|
||||
export type VcsStatusOperation<E = never> = (input?: Endpoint25_0Input) => Effect.Effect<Endpoint25_0Output, E>
|
||||
export type Endpoint25_0Output = EffectValue<ReturnType<RawClient["server.vcs"]["vcs.get"]>>
|
||||
export type VcsGetOperation<E = never> = (input?: Endpoint25_0Input) => Effect.Effect<Endpoint25_0Output, E>
|
||||
|
||||
type Endpoint25_1Request = Parameters<RawClient["server.vcs"]["vcs.diff"]>[0]
|
||||
export type Endpoint25_1Input = {
|
||||
readonly location?: Endpoint25_1Request["query"]["location"]
|
||||
readonly mode: Endpoint25_1Request["query"]["mode"]
|
||||
readonly context?: Endpoint25_1Request["query"]["context"]
|
||||
type Endpoint25_1Request = Parameters<RawClient["server.vcs"]["vcs.status"]>[0]
|
||||
export type Endpoint25_1Input = { readonly location?: Endpoint25_1Request["query"]["location"] }
|
||||
export type Endpoint25_1Output = EffectValue<ReturnType<RawClient["server.vcs"]["vcs.status"]>>
|
||||
export type VcsStatusOperation<E = never> = (input?: Endpoint25_1Input) => Effect.Effect<Endpoint25_1Output, E>
|
||||
|
||||
type Endpoint25_2Request = Parameters<RawClient["server.vcs"]["vcs.diff"]>[0]
|
||||
export type Endpoint25_2Input = {
|
||||
readonly location?: Endpoint25_2Request["query"]["location"]
|
||||
readonly mode: Endpoint25_2Request["query"]["mode"]
|
||||
readonly context?: Endpoint25_2Request["query"]["context"]
|
||||
}
|
||||
export type Endpoint25_1Output = EffectValue<ReturnType<RawClient["server.vcs"]["vcs.diff"]>>
|
||||
export type VcsDiffOperation<E = never> = (input: Endpoint25_1Input) => Effect.Effect<Endpoint25_1Output, E>
|
||||
export type Endpoint25_2Output = EffectValue<ReturnType<RawClient["server.vcs"]["vcs.diff"]>>
|
||||
export type VcsDiffOperation<E = never> = (input: Endpoint25_2Input) => Effect.Effect<Endpoint25_2Output, E>
|
||||
|
||||
export interface VcsApi<E = never> {
|
||||
readonly get: VcsGetOperation<E>
|
||||
readonly status: VcsStatusOperation<E>
|
||||
readonly diff: VcsDiffOperation<E>
|
||||
}
|
||||
|
||||
export type Endpoint26_0Output = EffectValue<ReturnType<RawClient["server.debug"]["debug.location"]>>
|
||||
export type DebugLocationListOperation<E = never> = () => Effect.Effect<Endpoint26_0Output, E>
|
||||
type Endpoint26_0Request = Parameters<RawClient["server.path"]["path.get"]>[0]
|
||||
export type Endpoint26_0Input = { readonly location?: Endpoint26_0Request["query"]["location"] }
|
||||
export type Endpoint26_0Output = EffectValue<ReturnType<RawClient["server.path"]["path.get"]>>
|
||||
export type PathGetOperation<E = never> = (input?: Endpoint26_0Input) => Effect.Effect<Endpoint26_0Output, E>
|
||||
|
||||
type Endpoint26_1Request = Parameters<RawClient["server.debug"]["debug.location.evict"]>[0]
|
||||
export type Endpoint26_1Input = { readonly location?: Endpoint26_1Request["query"]["location"] }
|
||||
export type Endpoint26_1Output = EffectValue<ReturnType<RawClient["server.debug"]["debug.location.evict"]>>
|
||||
export type DebugLocationEvictOperation<E = never> = (input?: Endpoint26_1Input) => Effect.Effect<Endpoint26_1Output, E>
|
||||
export interface PathApi<E = never> {
|
||||
readonly get: PathGetOperation<E>
|
||||
}
|
||||
|
||||
export type Endpoint27_0Output = EffectValue<ReturnType<RawClient["server.debug"]["debug.location"]>>
|
||||
export type DebugLocationListOperation<E = never> = () => Effect.Effect<Endpoint27_0Output, E>
|
||||
|
||||
type Endpoint27_1Request = Parameters<RawClient["server.debug"]["debug.location.evict"]>[0]
|
||||
export type Endpoint27_1Input = { readonly location?: Endpoint27_1Request["query"]["location"] }
|
||||
export type Endpoint27_1Output = EffectValue<ReturnType<RawClient["server.debug"]["debug.location.evict"]>>
|
||||
export type DebugLocationEvictOperation<E = never> = (input?: Endpoint27_1Input) => Effect.Effect<Endpoint27_1Output, E>
|
||||
|
||||
export interface DebugApi<E = never> {
|
||||
readonly location: { readonly list: DebugLocationListOperation<E>; readonly evict: DebugLocationEvictOperation<E> }
|
||||
@@ -1069,5 +1100,6 @@ export interface AppApi<E = never> {
|
||||
readonly reference: ReferenceApi<E>
|
||||
readonly projectCopy: ProjectCopyApi<E>
|
||||
readonly vcs: VcsApi<E>
|
||||
readonly path: PathApi<E>
|
||||
readonly debug: DebugApi<E>
|
||||
}
|
||||
|
||||
@@ -977,21 +977,26 @@ const Endpoint19_0 = (raw: RawClient["server.event"]) => () =>
|
||||
|
||||
const adaptGroup19 = (raw: RawClient["server.event"]) => ({ subscribe: Endpoint19_0(raw) })
|
||||
|
||||
type Endpoint20_0Request = Parameters<RawClient["server.pty"]["pty.list"]>[0]
|
||||
type Endpoint20_0Request = Parameters<RawClient["server.pty"]["pty.shells"]>[0]
|
||||
type Endpoint20_0Input = { readonly location?: Endpoint20_0Request["query"]["location"] }
|
||||
const Endpoint20_0 = (raw: RawClient["server.pty"]) => (input?: Endpoint20_0Input) =>
|
||||
raw["pty.shells"]({ query: { location: input?.["location"] } }).pipe(Effect.mapError(mapClientError))
|
||||
|
||||
type Endpoint20_1Request = Parameters<RawClient["server.pty"]["pty.list"]>[0]
|
||||
type Endpoint20_1Input = { readonly location?: Endpoint20_1Request["query"]["location"] }
|
||||
const Endpoint20_1 = (raw: RawClient["server.pty"]) => (input?: Endpoint20_1Input) =>
|
||||
raw["pty.list"]({ query: { location: input?.["location"] } }).pipe(Effect.mapError(mapClientError))
|
||||
|
||||
type Endpoint20_1Request = Parameters<RawClient["server.pty"]["pty.create"]>[0]
|
||||
type Endpoint20_1Input = {
|
||||
readonly location?: Endpoint20_1Request["query"]["location"]
|
||||
readonly command?: Endpoint20_1Request["payload"]["command"]
|
||||
readonly args?: Endpoint20_1Request["payload"]["args"]
|
||||
readonly cwd?: Endpoint20_1Request["payload"]["cwd"]
|
||||
readonly title?: Endpoint20_1Request["payload"]["title"]
|
||||
readonly env?: Endpoint20_1Request["payload"]["env"]
|
||||
type Endpoint20_2Request = Parameters<RawClient["server.pty"]["pty.create"]>[0]
|
||||
type Endpoint20_2Input = {
|
||||
readonly location?: Endpoint20_2Request["query"]["location"]
|
||||
readonly command?: Endpoint20_2Request["payload"]["command"]
|
||||
readonly args?: Endpoint20_2Request["payload"]["args"]
|
||||
readonly cwd?: Endpoint20_2Request["payload"]["cwd"]
|
||||
readonly title?: Endpoint20_2Request["payload"]["title"]
|
||||
readonly env?: Endpoint20_2Request["payload"]["env"]
|
||||
}
|
||||
const Endpoint20_1 = (raw: RawClient["server.pty"]) => (input?: Endpoint20_1Input) =>
|
||||
const Endpoint20_2 = (raw: RawClient["server.pty"]) => (input?: Endpoint20_2Input) =>
|
||||
raw["pty.create"]({
|
||||
query: { location: input?.["location"] },
|
||||
payload: {
|
||||
@@ -1003,46 +1008,61 @@ const Endpoint20_1 = (raw: RawClient["server.pty"]) => (input?: Endpoint20_1Inpu
|
||||
},
|
||||
}).pipe(Effect.mapError(mapClientError))
|
||||
|
||||
type Endpoint20_2Request = Parameters<RawClient["server.pty"]["pty.get"]>[0]
|
||||
type Endpoint20_2Input = {
|
||||
readonly ptyID: Endpoint20_2Request["params"]["ptyID"]
|
||||
readonly location?: Endpoint20_2Request["query"]["location"]
|
||||
type Endpoint20_3Request = Parameters<RawClient["server.pty"]["pty.get"]>[0]
|
||||
type Endpoint20_3Input = {
|
||||
readonly ptyID: Endpoint20_3Request["params"]["ptyID"]
|
||||
readonly location?: Endpoint20_3Request["query"]["location"]
|
||||
}
|
||||
const Endpoint20_2 = (raw: RawClient["server.pty"]) => (input: Endpoint20_2Input) =>
|
||||
const Endpoint20_3 = (raw: RawClient["server.pty"]) => (input: Endpoint20_3Input) =>
|
||||
raw["pty.get"]({ params: { ptyID: input["ptyID"] }, query: { location: input["location"] } }).pipe(
|
||||
Effect.mapError(mapClientError),
|
||||
)
|
||||
|
||||
type Endpoint20_3Request = Parameters<RawClient["server.pty"]["pty.update"]>[0]
|
||||
type Endpoint20_3Input = {
|
||||
readonly ptyID: Endpoint20_3Request["params"]["ptyID"]
|
||||
readonly location?: Endpoint20_3Request["query"]["location"]
|
||||
readonly title?: Endpoint20_3Request["payload"]["title"]
|
||||
readonly size?: Endpoint20_3Request["payload"]["size"]
|
||||
type Endpoint20_4Request = Parameters<RawClient["server.pty"]["pty.update"]>[0]
|
||||
type Endpoint20_4Input = {
|
||||
readonly ptyID: Endpoint20_4Request["params"]["ptyID"]
|
||||
readonly location?: Endpoint20_4Request["query"]["location"]
|
||||
readonly title?: Endpoint20_4Request["payload"]["title"]
|
||||
readonly size?: Endpoint20_4Request["payload"]["size"]
|
||||
}
|
||||
const Endpoint20_3 = (raw: RawClient["server.pty"]) => (input: Endpoint20_3Input) =>
|
||||
const Endpoint20_4 = (raw: RawClient["server.pty"]) => (input: Endpoint20_4Input) =>
|
||||
raw["pty.update"]({
|
||||
params: { ptyID: input["ptyID"] },
|
||||
query: { location: input["location"] },
|
||||
payload: { title: input["title"], size: input["size"] },
|
||||
}).pipe(Effect.mapError(mapClientError))
|
||||
|
||||
type Endpoint20_4Request = Parameters<RawClient["server.pty"]["pty.remove"]>[0]
|
||||
type Endpoint20_4Input = {
|
||||
readonly ptyID: Endpoint20_4Request["params"]["ptyID"]
|
||||
readonly location?: Endpoint20_4Request["query"]["location"]
|
||||
type Endpoint20_5Request = Parameters<RawClient["server.pty"]["pty.remove"]>[0]
|
||||
type Endpoint20_5Input = {
|
||||
readonly ptyID: Endpoint20_5Request["params"]["ptyID"]
|
||||
readonly location?: Endpoint20_5Request["query"]["location"]
|
||||
}
|
||||
const Endpoint20_4 = (raw: RawClient["server.pty"]) => (input: Endpoint20_4Input) =>
|
||||
const Endpoint20_5 = (raw: RawClient["server.pty"]) => (input: Endpoint20_5Input) =>
|
||||
raw["pty.remove"]({ params: { ptyID: input["ptyID"] }, query: { location: input["location"] } }).pipe(
|
||||
Effect.mapError(mapClientError),
|
||||
)
|
||||
|
||||
type Endpoint20_6Request = Parameters<RawClient["server.pty"]["pty.connectToken"]>[0]
|
||||
type Endpoint20_6Input = {
|
||||
readonly ptyID: Endpoint20_6Request["params"]["ptyID"]
|
||||
readonly location?: Endpoint20_6Request["query"]["location"]
|
||||
readonly "x-opencode-ticket"?: Endpoint20_6Request["headers"]["x-opencode-ticket"]
|
||||
}
|
||||
const Endpoint20_6 = (raw: RawClient["server.pty"]) => (input: Endpoint20_6Input) =>
|
||||
raw["pty.connectToken"]({
|
||||
params: { ptyID: input["ptyID"] },
|
||||
query: { location: input["location"] },
|
||||
headers: { "x-opencode-ticket": input["x-opencode-ticket"] },
|
||||
}).pipe(Effect.mapError(mapClientError))
|
||||
|
||||
const adaptGroup20 = (raw: RawClient["server.pty"]) => ({
|
||||
list: Endpoint20_0(raw),
|
||||
create: Endpoint20_1(raw),
|
||||
get: Endpoint20_2(raw),
|
||||
update: Endpoint20_3(raw),
|
||||
remove: Endpoint20_4(raw),
|
||||
shells: Endpoint20_0(raw),
|
||||
list: Endpoint20_1(raw),
|
||||
create: Endpoint20_2(raw),
|
||||
get: Endpoint20_3(raw),
|
||||
update: Endpoint20_4(raw),
|
||||
remove: Endpoint20_5(raw),
|
||||
connectToken: Endpoint20_6(raw),
|
||||
})
|
||||
|
||||
type Endpoint21_0Request = Parameters<RawClient["server.shell"]["shell.list"]>[0]
|
||||
@@ -1214,34 +1234,50 @@ const adaptGroup24 = (raw: RawClient["server.projectCopy"]) => ({
|
||||
refresh: Endpoint24_2(raw),
|
||||
})
|
||||
|
||||
type Endpoint25_0Request = Parameters<RawClient["server.vcs"]["vcs.status"]>[0]
|
||||
type Endpoint25_0Request = Parameters<RawClient["server.vcs"]["vcs.get"]>[0]
|
||||
type Endpoint25_0Input = { readonly location?: Endpoint25_0Request["query"]["location"] }
|
||||
const Endpoint25_0 = (raw: RawClient["server.vcs"]) => (input?: Endpoint25_0Input) =>
|
||||
raw["vcs.get"]({ query: { location: input?.["location"] } }).pipe(Effect.mapError(mapClientError))
|
||||
|
||||
type Endpoint25_1Request = Parameters<RawClient["server.vcs"]["vcs.status"]>[0]
|
||||
type Endpoint25_1Input = { readonly location?: Endpoint25_1Request["query"]["location"] }
|
||||
const Endpoint25_1 = (raw: RawClient["server.vcs"]) => (input?: Endpoint25_1Input) =>
|
||||
raw["vcs.status"]({ query: { location: input?.["location"] } }).pipe(Effect.mapError(mapClientError))
|
||||
|
||||
type Endpoint25_1Request = Parameters<RawClient["server.vcs"]["vcs.diff"]>[0]
|
||||
type Endpoint25_1Input = {
|
||||
readonly location?: Endpoint25_1Request["query"]["location"]
|
||||
readonly mode: Endpoint25_1Request["query"]["mode"]
|
||||
readonly context?: Endpoint25_1Request["query"]["context"]
|
||||
type Endpoint25_2Request = Parameters<RawClient["server.vcs"]["vcs.diff"]>[0]
|
||||
type Endpoint25_2Input = {
|
||||
readonly location?: Endpoint25_2Request["query"]["location"]
|
||||
readonly mode: Endpoint25_2Request["query"]["mode"]
|
||||
readonly context?: Endpoint25_2Request["query"]["context"]
|
||||
}
|
||||
const Endpoint25_1 = (raw: RawClient["server.vcs"]) => (input: Endpoint25_1Input) =>
|
||||
const Endpoint25_2 = (raw: RawClient["server.vcs"]) => (input: Endpoint25_2Input) =>
|
||||
raw["vcs.diff"]({ query: { location: input["location"], mode: input["mode"], context: input["context"] } }).pipe(
|
||||
Effect.mapError(mapClientError),
|
||||
)
|
||||
|
||||
const adaptGroup25 = (raw: RawClient["server.vcs"]) => ({ status: Endpoint25_0(raw), diff: Endpoint25_1(raw) })
|
||||
const adaptGroup25 = (raw: RawClient["server.vcs"]) => ({
|
||||
get: Endpoint25_0(raw),
|
||||
status: Endpoint25_1(raw),
|
||||
diff: Endpoint25_2(raw),
|
||||
})
|
||||
|
||||
const Endpoint26_0 = (raw: RawClient["server.debug"]) => () =>
|
||||
type Endpoint26_0Request = Parameters<RawClient["server.path"]["path.get"]>[0]
|
||||
type Endpoint26_0Input = { readonly location?: Endpoint26_0Request["query"]["location"] }
|
||||
const Endpoint26_0 = (raw: RawClient["server.path"]) => (input?: Endpoint26_0Input) =>
|
||||
raw["path.get"]({ query: { location: input?.["location"] } }).pipe(Effect.mapError(mapClientError))
|
||||
|
||||
const adaptGroup26 = (raw: RawClient["server.path"]) => ({ get: Endpoint26_0(raw) })
|
||||
|
||||
const Endpoint27_0 = (raw: RawClient["server.debug"]) => () =>
|
||||
raw["debug.location"]({}).pipe(Effect.mapError(mapClientError))
|
||||
|
||||
type Endpoint26_1Request = Parameters<RawClient["server.debug"]["debug.location.evict"]>[0]
|
||||
type Endpoint26_1Input = { readonly location?: Endpoint26_1Request["query"]["location"] }
|
||||
const Endpoint26_1 = (raw: RawClient["server.debug"]) => (input?: Endpoint26_1Input) =>
|
||||
type Endpoint27_1Request = Parameters<RawClient["server.debug"]["debug.location.evict"]>[0]
|
||||
type Endpoint27_1Input = { readonly location?: Endpoint27_1Request["query"]["location"] }
|
||||
const Endpoint27_1 = (raw: RawClient["server.debug"]) => (input?: Endpoint27_1Input) =>
|
||||
raw["debug.location.evict"]({ query: { location: input?.["location"] } }).pipe(Effect.mapError(mapClientError))
|
||||
|
||||
const adaptGroup26 = (raw: RawClient["server.debug"]) => ({
|
||||
location: { list: Endpoint26_0(raw), evict: Endpoint26_1(raw) },
|
||||
const adaptGroup27 = (raw: RawClient["server.debug"]) => ({
|
||||
location: { list: Endpoint27_0(raw), evict: Endpoint27_1(raw) },
|
||||
})
|
||||
|
||||
const adaptClient = (raw: RawClient) => ({
|
||||
@@ -1271,7 +1307,8 @@ const adaptClient = (raw: RawClient) => ({
|
||||
reference: adaptGroup23(raw["server.reference"]),
|
||||
projectCopy: adaptGroup24(raw["server.projectCopy"]),
|
||||
vcs: adaptGroup25(raw["server.vcs"]),
|
||||
debug: adaptGroup26(raw["server.debug"]),
|
||||
path: adaptGroup26(raw["server.path"]),
|
||||
debug: adaptGroup27(raw["server.debug"]),
|
||||
})
|
||||
|
||||
export const make = (options?: { readonly baseUrl?: URL | string }) =>
|
||||
|
||||
@@ -3,13 +3,22 @@ type Client = ReturnType<typeof import("./generated/client.js").make>
|
||||
export type AgentApi = Client["agent"]
|
||||
export type CommandApi = Client["command"]
|
||||
export type EventApi = Client["event"]
|
||||
export type FileApi = Client["file"]
|
||||
export type IntegrationApi = Client["integration"]
|
||||
export type MessageApi = Client["message"]
|
||||
export type McpApi = Client["mcp"]
|
||||
export type ModelApi = Client["model"]
|
||||
export type PluginApi = Client["plugin"]
|
||||
export type PermissionApi = Client["permission"]
|
||||
export type PathApi = Client["path"]
|
||||
export type ProjectApi = Client["project"]
|
||||
export type ProviderApi = Client["provider"]
|
||||
export type QuestionApi = Client["question"]
|
||||
export type ReferenceApi = Client["reference"]
|
||||
export type SessionApi = Client["session"]
|
||||
export type SkillApi = Client["skill"]
|
||||
export type PtyApi = Client["pty"]
|
||||
export type VcsApi = Client["vcs"]
|
||||
|
||||
export interface CatalogApi {
|
||||
readonly provider: ProviderApi
|
||||
|
||||
@@ -162,6 +162,8 @@ import type {
|
||||
SkillListInput,
|
||||
SkillListOutput,
|
||||
EventSubscribeOutput,
|
||||
PtyShellsInput,
|
||||
PtyShellsOutput,
|
||||
PtyListInput,
|
||||
PtyListOutput,
|
||||
PtyCreateInput,
|
||||
@@ -172,6 +174,8 @@ import type {
|
||||
PtyUpdateOutput,
|
||||
PtyRemoveInput,
|
||||
PtyRemoveOutput,
|
||||
PtyConnectTokenInput,
|
||||
PtyConnectTokenOutput,
|
||||
ShellListInput,
|
||||
ShellListOutput,
|
||||
ShellCreateInput,
|
||||
@@ -200,10 +204,14 @@ import type {
|
||||
ProjectCopyRemoveOutput,
|
||||
ProjectCopyRefreshInput,
|
||||
ProjectCopyRefreshOutput,
|
||||
VcsGetInput,
|
||||
VcsGetOutput,
|
||||
VcsStatusInput,
|
||||
VcsStatusOutput,
|
||||
VcsDiffInput,
|
||||
VcsDiffOutput,
|
||||
PathGetInput,
|
||||
PathGetOutput,
|
||||
DebugLocationListOutput,
|
||||
DebugLocationEvictInput,
|
||||
DebugLocationEvictOutput,
|
||||
@@ -1428,6 +1436,18 @@ export function make(options: ClientOptions) {
|
||||
),
|
||||
},
|
||||
pty: {
|
||||
shells: (input?: PtyShellsInput, requestOptions?: RequestOptions) =>
|
||||
request<PtyShellsOutput>(
|
||||
{
|
||||
method: "GET",
|
||||
path: `/api/pty/shells`,
|
||||
query: { location: input?.["location"] },
|
||||
successStatus: 200,
|
||||
declaredStatuses: [401, 400],
|
||||
empty: false,
|
||||
},
|
||||
requestOptions,
|
||||
),
|
||||
list: (input?: PtyListInput, requestOptions?: RequestOptions) =>
|
||||
request<PtyListOutput>(
|
||||
{
|
||||
@@ -1496,6 +1516,19 @@ export function make(options: ClientOptions) {
|
||||
},
|
||||
requestOptions,
|
||||
),
|
||||
connectToken: (input: PtyConnectTokenInput, requestOptions?: RequestOptions) =>
|
||||
request<PtyConnectTokenOutput>(
|
||||
{
|
||||
method: "POST",
|
||||
path: `/api/pty/${encodeURIComponent(input.ptyID)}/connect-token`,
|
||||
query: { location: input["location"] },
|
||||
headers: { "x-opencode-ticket": input["x-opencode-ticket"] },
|
||||
successStatus: 200,
|
||||
declaredStatuses: [403, 404, 401, 400],
|
||||
empty: false,
|
||||
},
|
||||
requestOptions,
|
||||
),
|
||||
},
|
||||
shell: {
|
||||
list: (input?: ShellListInput, requestOptions?: RequestOptions) =>
|
||||
@@ -1683,6 +1716,18 @@ export function make(options: ClientOptions) {
|
||||
),
|
||||
},
|
||||
vcs: {
|
||||
get: (input?: VcsGetInput, requestOptions?: RequestOptions) =>
|
||||
request<VcsGetOutput>(
|
||||
{
|
||||
method: "GET",
|
||||
path: `/api/vcs`,
|
||||
query: { location: input?.["location"] },
|
||||
successStatus: 200,
|
||||
declaredStatuses: [401, 400],
|
||||
empty: false,
|
||||
},
|
||||
requestOptions,
|
||||
),
|
||||
status: (input?: VcsStatusInput, requestOptions?: RequestOptions) =>
|
||||
request<VcsStatusOutput>(
|
||||
{
|
||||
@@ -1708,6 +1753,20 @@ export function make(options: ClientOptions) {
|
||||
requestOptions,
|
||||
),
|
||||
},
|
||||
path: {
|
||||
get: (input?: PathGetInput, requestOptions?: RequestOptions) =>
|
||||
request<PathGetOutput>(
|
||||
{
|
||||
method: "GET",
|
||||
path: `/api/path`,
|
||||
query: { location: input?.["location"] },
|
||||
successStatus: 200,
|
||||
declaredStatuses: [401, 400],
|
||||
empty: false,
|
||||
},
|
||||
requestOptions,
|
||||
),
|
||||
},
|
||||
debug: {
|
||||
location: {
|
||||
list: (requestOptions?: RequestOptions) =>
|
||||
|
||||
@@ -501,6 +501,10 @@ export type QuestionTool = { messageID: string; callID: string }
|
||||
|
||||
export type QuestionAnswer = Array<string>
|
||||
|
||||
export type PtyShell = { path: string; name: string; acceptable: boolean }
|
||||
|
||||
export type PtyTicketConnectToken = { ticket: string; expires_in: number }
|
||||
|
||||
export type ShellInfo1 = {
|
||||
id: string
|
||||
status: "running" | "exited" | "timeout" | "killed"
|
||||
@@ -526,6 +530,8 @@ export type ReferenceGitSource = {
|
||||
|
||||
export type ProjectCopyCopy = { directory: string }
|
||||
|
||||
export type VcsInfo = { branch?: string; defaultBranch?: string }
|
||||
|
||||
export type VcsFileStatus = {
|
||||
file: string
|
||||
additions: number
|
||||
@@ -533,6 +539,8 @@ export type VcsFileStatus = {
|
||||
status: "added" | "deleted" | "modified"
|
||||
}
|
||||
|
||||
export type PathInfo = { home: string; state: string; config: string; worktree: string; directory: string }
|
||||
|
||||
export type SessionMessageModelSelected = {
|
||||
id: string
|
||||
metadata?: { [x: string]: JsonValue }
|
||||
@@ -549,6 +557,7 @@ export type CommandInfo = {
|
||||
agent?: string
|
||||
model?: ModelRef
|
||||
subtask?: boolean
|
||||
source?: "command" | "mcp"
|
||||
}
|
||||
|
||||
export type ProviderRequest = {
|
||||
@@ -2527,6 +2536,10 @@ export type PtyNotFoundError = { readonly _tag: "PtyNotFoundError"; readonly pty
|
||||
export const isPtyNotFoundError = (value: unknown): value is PtyNotFoundError =>
|
||||
typeof value === "object" && value !== null && "_tag" in value && value["_tag"] === "PtyNotFoundError"
|
||||
|
||||
export type ForbiddenError = { readonly _tag: "ForbiddenError"; readonly message: string }
|
||||
export const isForbiddenError = (value: unknown): value is ForbiddenError =>
|
||||
typeof value === "object" && value !== null && "_tag" in value && value["_tag"] === "ForbiddenError"
|
||||
|
||||
export type ShellNotFoundError = { readonly _tag: "ShellNotFoundError"; readonly id: string; readonly message: string }
|
||||
export const isShellNotFoundError = (value: unknown): value is ShellNotFoundError =>
|
||||
typeof value === "object" && value !== null && "_tag" in value && value["_tag"] === "ShellNotFoundError"
|
||||
@@ -4646,6 +4659,17 @@ export type SkillListOutput = {
|
||||
|
||||
export type EventSubscribeOutput = V2Event
|
||||
|
||||
export type PtyShellsInput = {
|
||||
readonly location?: {
|
||||
readonly location?: { readonly directory?: string | undefined; readonly workspace?: string | undefined } | undefined
|
||||
}["location"]
|
||||
}
|
||||
|
||||
export type PtyShellsOutput = {
|
||||
location: { directory: string; workspaceID?: string; project: { id: string; directory: string } }
|
||||
data: Array<PtyShell>
|
||||
}
|
||||
|
||||
export type PtyListInput = {
|
||||
readonly location?: {
|
||||
readonly location?: { readonly directory?: string | undefined; readonly workspace?: string | undefined } | undefined
|
||||
@@ -4741,6 +4765,19 @@ export type PtyRemoveInput = {
|
||||
|
||||
export type PtyRemoveOutput = void
|
||||
|
||||
export type PtyConnectTokenInput = {
|
||||
readonly ptyID: { readonly ptyID: string }["ptyID"]
|
||||
readonly location?: {
|
||||
readonly location?: { readonly directory?: string | undefined; readonly workspace?: string | undefined } | undefined
|
||||
}["location"]
|
||||
readonly "x-opencode-ticket"?: { readonly "x-opencode-ticket"?: string | undefined }["x-opencode-ticket"]
|
||||
}
|
||||
|
||||
export type PtyConnectTokenOutput = {
|
||||
location: { directory: string; workspaceID?: string; project: { id: string; directory: string } }
|
||||
data: PtyTicketConnectToken
|
||||
}
|
||||
|
||||
export type ShellListInput = {
|
||||
readonly location?: {
|
||||
readonly location?: { readonly directory?: string | undefined; readonly workspace?: string | undefined } | undefined
|
||||
@@ -4918,6 +4955,17 @@ export type ProjectCopyRefreshInput = {
|
||||
|
||||
export type ProjectCopyRefreshOutput = void
|
||||
|
||||
export type VcsGetInput = {
|
||||
readonly location?: {
|
||||
readonly location?: { readonly directory?: string | undefined; readonly workspace?: string | undefined } | undefined
|
||||
}["location"]
|
||||
}
|
||||
|
||||
export type VcsGetOutput = {
|
||||
location: { directory: string; workspaceID?: string; project: { id: string; directory: string } }
|
||||
data: VcsInfo
|
||||
}
|
||||
|
||||
export type VcsStatusInput = {
|
||||
readonly location?: {
|
||||
readonly location?: { readonly directory?: string | undefined; readonly workspace?: string | undefined } | undefined
|
||||
@@ -4952,6 +5000,14 @@ export type VcsDiffOutput = {
|
||||
data: Array<FileDiffInfo>
|
||||
}
|
||||
|
||||
export type PathGetInput = {
|
||||
readonly location?: {
|
||||
readonly location?: { readonly directory?: string | undefined; readonly workspace?: string | undefined } | undefined
|
||||
}["location"]
|
||||
}
|
||||
|
||||
export type PathGetOutput = PathInfo
|
||||
|
||||
export type DebugLocationListOutput = Array<LocationRef>
|
||||
|
||||
export type DebugLocationEvictInput = {
|
||||
|
||||
@@ -4,13 +4,22 @@ export type {
|
||||
CatalogApi,
|
||||
CommandApi,
|
||||
EventApi,
|
||||
FileApi,
|
||||
IntegrationApi,
|
||||
MessageApi,
|
||||
McpApi,
|
||||
ModelApi,
|
||||
PermissionApi,
|
||||
PathApi,
|
||||
PluginApi,
|
||||
ProjectApi,
|
||||
ProviderApi,
|
||||
QuestionApi,
|
||||
ReferenceApi,
|
||||
SessionApi,
|
||||
SkillApi,
|
||||
PtyApi,
|
||||
VcsApi,
|
||||
} from "./api.js"
|
||||
export type { EventSubscribeOutput as OpenCodeEvent } from "./generated/types"
|
||||
export type OpenCodeClient = ReturnType<typeof import("./generated/client").make>
|
||||
|
||||
@@ -31,6 +31,7 @@ test("exposes every standard HTTP API group", () => {
|
||||
"reference",
|
||||
"projectCopy",
|
||||
"vcs",
|
||||
"path",
|
||||
"debug",
|
||||
])
|
||||
expect(Object.keys(client.debug)).toEqual(["location"])
|
||||
@@ -42,12 +43,39 @@ test("exposes every standard HTTP API group", () => {
|
||||
expect(Object.keys(client.integration.oauth)).toEqual(["connect", "status", "complete", "cancel"])
|
||||
expect(Object.keys(client.integration.command)).toEqual(["connect", "status", "cancel"])
|
||||
expect(Object.keys(client.file)).toEqual(["read", "list", "find"])
|
||||
expect(Object.keys(client.vcs)).toEqual(["status", "diff"])
|
||||
expect(Object.keys(client.pty)).toEqual(["list", "create", "get", "update", "remove"])
|
||||
expect(Object.keys(client.vcs)).toEqual(["get", "status", "diff"])
|
||||
expect(Object.keys(client.pty)).toEqual(["shells", "list", "create", "get", "update", "remove", "connectToken"])
|
||||
expect(Object.keys(client.shell)).toEqual(["list", "create", "get", "timeout", "output", "remove"])
|
||||
expect(Object.keys(client.project)).toEqual(["list", "current", "directories"])
|
||||
})
|
||||
|
||||
test("PTY connect token sends the required browser header", async () => {
|
||||
let request: Request | undefined
|
||||
const client = OpenCode.make({
|
||||
baseUrl: "http://localhost:3000",
|
||||
fetch: async (input, init) => {
|
||||
request = input instanceof Request ? input : new Request(input, init)
|
||||
return Response.json({
|
||||
location: { directory: "/tmp/project", project: { id: "proj_test", directory: "/tmp/project" } },
|
||||
data: { ticket: "ticket", expires_in: 60 },
|
||||
})
|
||||
},
|
||||
})
|
||||
|
||||
const result = await client.pty.connectToken({
|
||||
ptyID: "pty_test",
|
||||
location: { directory: "/tmp/project" },
|
||||
"x-opencode-ticket": "1",
|
||||
})
|
||||
|
||||
expect(result.data.ticket).toBe("ticket")
|
||||
expect(request?.method).toBe("POST")
|
||||
expect(request?.headers.get("x-opencode-ticket")).toBe("1")
|
||||
expect(request?.url).toBe(
|
||||
"http://localhost:3000/api/pty/pty_test/connect-token?location%5Bdirectory%5D=%2Ftmp%2Fproject",
|
||||
)
|
||||
})
|
||||
|
||||
test("server.get uses the public HTTP contract", async () => {
|
||||
let request: Request | undefined
|
||||
const client = OpenCode.make({
|
||||
|
||||
@@ -85,6 +85,7 @@ export const layer = (options?: ShellSelect.Options) => Layer.effect(
|
||||
name: mcpCommandName(prompt.server, prompt.name),
|
||||
template: "",
|
||||
description: prompt.description,
|
||||
source: "mcp",
|
||||
}),
|
||||
)
|
||||
})
|
||||
@@ -98,7 +99,10 @@ export const layer = (options?: ShellSelect.Options) => Layer.effect(
|
||||
return (yield* mcpCommands()).find((command) => command.name === name)
|
||||
}),
|
||||
list: Effect.fn("CommandV2.list")(function* () {
|
||||
const commands = Array.from(state.get().commands.values()) as Info[]
|
||||
const commands = Array.from(state.get().commands.values()).map((command) => ({
|
||||
...command,
|
||||
source: command.source ?? "command" as const,
|
||||
}))
|
||||
const names = new Set(commands.map((command) => command.name))
|
||||
return [
|
||||
...commands,
|
||||
|
||||
@@ -78,6 +78,7 @@ export class ExitedError extends Schema.TaggedErrorClass<ExitedError>()("Pty.Exi
|
||||
}) {}
|
||||
|
||||
export interface Interface {
|
||||
readonly shells: () => Effect.Effect<ReadonlyArray<Pty.Shell>>
|
||||
readonly list: () => Effect.Effect<Info[]>
|
||||
readonly get: (id: PtyID) => Effect.Effect<Info, NotFoundError>
|
||||
readonly create: (input: CreateInput) => Effect.Effect<Info>
|
||||
@@ -158,6 +159,10 @@ export const layer = (options?: ShellSelect.Options) => Layer.effect(
|
||||
return Array.from(sessions.values()).map((session) => session.info)
|
||||
})
|
||||
|
||||
const shells = Effect.fn("Pty.shells")(function* () {
|
||||
return yield* Effect.promise(() => ShellSelect.list(options))
|
||||
})
|
||||
|
||||
const get = Effect.fn("Pty.get")(function* (id: PtyID) {
|
||||
return (yield* requireSession(id)).info
|
||||
})
|
||||
@@ -309,7 +314,7 @@ export const layer = (options?: ShellSelect.Options) => Layer.effect(
|
||||
}
|
||||
})
|
||||
|
||||
return Service.of({ list, get, create, update, remove, write, attach })
|
||||
return Service.of({ shells, list, get, create, update, remove, write, attach })
|
||||
}),
|
||||
)
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ export * as Vcs from "./vcs"
|
||||
|
||||
import { Context, Effect, Layer } from "effect"
|
||||
import { FileDiff } from "@opencode-ai/schema/file-diff"
|
||||
import { FileStatus, Mode } from "@opencode-ai/schema/vcs"
|
||||
import { FileStatus, Info, Mode } from "@opencode-ai/schema/vcs"
|
||||
import { makeLocationNode } from "@opencode-ai/util/effect/app-node"
|
||||
import { FSUtil } from "@opencode-ai/util/fs-util"
|
||||
import { Location } from "./location"
|
||||
@@ -10,13 +10,14 @@ import { AppProcess } from "@opencode-ai/util/process"
|
||||
import { VcsGit } from "./vcs/git"
|
||||
import { VcsHg } from "./vcs/hg"
|
||||
|
||||
export { FileStatus, Mode }
|
||||
export { FileStatus, Info, Mode }
|
||||
|
||||
export interface DiffOptions {
|
||||
readonly context?: number
|
||||
}
|
||||
|
||||
export interface Interface {
|
||||
readonly info: () => Effect.Effect<Info>
|
||||
readonly status: () => Effect.Effect<FileStatus[]>
|
||||
readonly diff: (mode: Mode, options?: DiffOptions) => Effect.Effect<FileDiff.Info[]>
|
||||
}
|
||||
@@ -40,6 +41,10 @@ const layer = Layer.effect(
|
||||
const location = yield* Location.Service
|
||||
const impl = adapter(proc, fs, location)
|
||||
return Service.of({
|
||||
info: Effect.fn("Vcs.info")(function* () {
|
||||
if (!impl) return {}
|
||||
return yield* impl.info()
|
||||
}),
|
||||
status: Effect.fn("Vcs.status")(function* () {
|
||||
if (!impl) return []
|
||||
return yield* impl.status()
|
||||
|
||||
@@ -20,6 +20,12 @@ export function make(proc: AppProcess.Interface, input: { directory: string; wor
|
||||
const ctx: Ctx = { git: makeGit(proc), directory: input.directory, worktree: input.worktree }
|
||||
|
||||
return {
|
||||
info: Effect.fn("VcsGit.info")(function* () {
|
||||
const [branch, root] = yield* Effect.all([ctx.git.branch(ctx.directory), ctx.git.defaultBranch(ctx.directory)], {
|
||||
concurrency: 2,
|
||||
})
|
||||
return { branch, defaultBranch: root?.name }
|
||||
}),
|
||||
status: Effect.fn("VcsGit.status")(function* () {
|
||||
const git = ctx.git
|
||||
const ref = (yield* git.hasHead(ctx.directory)) ? "HEAD" : undefined
|
||||
|
||||
@@ -73,6 +73,9 @@ export function make(
|
||||
})
|
||||
|
||||
return {
|
||||
info: Effect.fn("VcsHg.info")(function* () {
|
||||
return { branch: yield* hg.branch(), defaultBranch: "default" }
|
||||
}),
|
||||
status: Effect.fn("VcsHg.status")(function* () {
|
||||
const [items, batch] = yield* Effect.all(
|
||||
// Zero-context patches are enough to count changed lines.
|
||||
|
||||
@@ -59,6 +59,7 @@ describe("CommandV2", () => {
|
||||
providerID: ProviderV2.ID.make("anthropic"),
|
||||
variant: ModelV2.VariantID.make("high"),
|
||||
},
|
||||
source: "command",
|
||||
}),
|
||||
])
|
||||
}),
|
||||
|
||||
@@ -95,9 +95,10 @@ Review files`,
|
||||
variant: ModelV2.VariantID.make("high"),
|
||||
},
|
||||
subtask: true,
|
||||
source: "command",
|
||||
}),
|
||||
CommandV2.Info.make({ name: "empty", template: "" }),
|
||||
CommandV2.Info.make({ name: "nested/docs", template: "Write docs" }),
|
||||
CommandV2.Info.make({ name: "empty", template: "", source: "command" }),
|
||||
CommandV2.Info.make({ name: "nested/docs", template: "Write docs", source: "command" }),
|
||||
])
|
||||
|
||||
yield* Effect.promise(() => fs.writeFile(path.join(tmp.path, "commands", "review.md"), "Review again"))
|
||||
|
||||
@@ -90,6 +90,18 @@ const waitForOutput = (output: Queue.Queue<string>, text: string) =>
|
||||
}),
|
||||
)
|
||||
|
||||
describe("Pty.shells", () => {
|
||||
it.live("lists available shells", () =>
|
||||
Effect.gen(function* () {
|
||||
const pty = yield* Pty.Service
|
||||
const shells = yield* pty.shells()
|
||||
|
||||
expect(shells.length).toBeGreaterThan(0)
|
||||
expect(shells.every((shell) => shell.path && shell.name && typeof shell.acceptable === "boolean")).toBe(true)
|
||||
}),
|
||||
)
|
||||
})
|
||||
|
||||
describe("pty", () => {
|
||||
it.live("returns typed not found errors for missing sessions", () =>
|
||||
Effect.gen(function* () {
|
||||
|
||||
@@ -152,6 +152,7 @@ describeHg("Vcs mercurial", () => {
|
||||
await commitAll(directory, "initial")
|
||||
})
|
||||
const vcs = yield* Vcs.Service
|
||||
expect(yield* vcs.info()).toEqual({ branch: "default", defaultBranch: "default" })
|
||||
expect(yield* vcs.diff("branch")).toEqual([])
|
||||
|
||||
yield* Effect.promise(async () => {
|
||||
|
||||
@@ -53,6 +53,7 @@ describe("Vcs", () => {
|
||||
withTmp((directory) =>
|
||||
Effect.gen(function* () {
|
||||
const vcs = yield* Vcs.Service
|
||||
expect(yield* vcs.info()).toEqual({})
|
||||
expect(yield* vcs.status()).toEqual([])
|
||||
expect(yield* vcs.diff("working")).toEqual([])
|
||||
expect(yield* vcs.diff("branch")).toEqual([])
|
||||
@@ -155,6 +156,7 @@ describe("Vcs", () => {
|
||||
await commitAll(directory, "initial")
|
||||
})
|
||||
const vcs = yield* Vcs.Service
|
||||
expect(yield* vcs.info()).toEqual({ branch: "main", defaultBranch: "main" })
|
||||
expect(yield* vcs.diff("branch")).toEqual([])
|
||||
|
||||
yield* Effect.promise(async () => {
|
||||
|
||||
@@ -30,6 +30,7 @@ import { CredentialGroup } from "./groups/credential.js"
|
||||
import { ProjectGroup } from "./groups/project.js"
|
||||
import { ProjectCopyGroup } from "./groups/project-copy.js"
|
||||
import { VcsGroup } from "./groups/vcs.js"
|
||||
import { PathGroup } from "./groups/path.js"
|
||||
|
||||
type LocationGroups<LocationId extends HttpApiMiddleware.AnyId> =
|
||||
| HttpApiGroup.AddMiddleware<typeof LocationGroup, LocationId>
|
||||
@@ -50,6 +51,7 @@ type LocationGroups<LocationId extends HttpApiMiddleware.AnyId> =
|
||||
| HttpApiGroup.AddMiddleware<typeof ReferenceGroup, LocationId>
|
||||
| HttpApiGroup.AddMiddleware<typeof ProjectCopyGroup, LocationId>
|
||||
| HttpApiGroup.AddMiddleware<typeof VcsGroup, LocationId>
|
||||
| HttpApiGroup.AddMiddleware<typeof PathGroup, LocationId>
|
||||
|
||||
type SessionGroups<SessionLocationId extends HttpApiMiddleware.AnyId, SessionLocationService> =
|
||||
| ReturnType<typeof makeSessionGroup<SessionLocationId, SessionLocationService>>
|
||||
@@ -168,6 +170,7 @@ const makeApiFromGroup = <
|
||||
.add(ReferenceGroup.middleware(locationMiddleware))
|
||||
.add(ProjectCopyGroup.middleware(locationMiddleware))
|
||||
.add(VcsGroup.middleware(locationMiddleware))
|
||||
.add(PathGroup.middleware(locationMiddleware))
|
||||
.add(DebugGroup)
|
||||
.annotateMerge(
|
||||
OpenApi.annotations({
|
||||
|
||||
@@ -60,7 +60,8 @@ export const groupNames = {
|
||||
"server.project": "project",
|
||||
"server.projectCopy": "projectCopy",
|
||||
"server.vcs": "vcs",
|
||||
"server.path": "path",
|
||||
} as const
|
||||
|
||||
export const promiseOmitEndpoints = new Set(["pty.connect", "pty.connectToken"])
|
||||
export const effectOmitEndpoints = new Set(["fs.read", "pty.connect", "pty.connectToken"])
|
||||
export const promiseOmitEndpoints = new Set(["pty.connect"])
|
||||
export const effectOmitEndpoints = new Set(["fs.read", "pty.connect"])
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
import { Path } from "@opencode-ai/schema/path"
|
||||
import { HttpApiEndpoint, HttpApiGroup, OpenApi } from "effect/unstable/httpapi"
|
||||
import { LocationQuery, locationQueryOpenApi } from "./location.js"
|
||||
|
||||
export const PathGroup = HttpApiGroup.make("server.path")
|
||||
.add(
|
||||
HttpApiEndpoint.get("path.get", "/api/path", {
|
||||
query: LocationQuery,
|
||||
success: Path.Info,
|
||||
})
|
||||
.annotateMerge(locationQueryOpenApi)
|
||||
.annotateMerge(
|
||||
OpenApi.annotations({
|
||||
identifier: "v2.path.get",
|
||||
summary: "Get paths",
|
||||
description: "Get process and location paths.",
|
||||
}),
|
||||
),
|
||||
)
|
||||
.annotateMerge(OpenApi.annotations({ title: "path", description: "Location and process paths." }))
|
||||
@@ -19,6 +19,20 @@ export function hasPtyConnectTicketURL(url: URL) {
|
||||
}
|
||||
|
||||
export const PtyGroup = HttpApiGroup.make("server.pty")
|
||||
.add(
|
||||
HttpApiEndpoint.get("pty.shells", "/api/pty/shells", {
|
||||
query: LocationQuery,
|
||||
success: Location.response(Schema.Array(Pty.Shell)),
|
||||
})
|
||||
.annotateMerge(locationQueryOpenApi)
|
||||
.annotateMerge(
|
||||
OpenApi.annotations({
|
||||
identifier: "v2.pty.shells",
|
||||
summary: "List available shells",
|
||||
description: "List shells available for interactive terminal sessions.",
|
||||
}),
|
||||
),
|
||||
)
|
||||
.add(
|
||||
HttpApiEndpoint.get("pty.list", "/api/pty", {
|
||||
query: LocationQuery,
|
||||
@@ -101,13 +115,14 @@ export const PtyGroup = HttpApiGroup.make("server.pty")
|
||||
HttpApiEndpoint.post("pty.connectToken", "/api/pty/:ptyID/connect-token", {
|
||||
params: { ptyID: Pty.ID },
|
||||
query: LocationQuery,
|
||||
headers: Schema.Struct({ [PTY_CONNECT_TOKEN_HEADER]: Schema.optional(Schema.String) }),
|
||||
success: Location.response(PtyTicket.ConnectToken),
|
||||
error: [ForbiddenError, PtyNotFoundError],
|
||||
})
|
||||
.annotateMerge(locationQueryOpenApi)
|
||||
.annotateMerge(
|
||||
OpenApi.annotations({
|
||||
identifier: "v2.pty.connect.token",
|
||||
identifier: "v2.pty.connectToken",
|
||||
summary: "Create PTY WebSocket token",
|
||||
description: "Create a short-lived single-use ticket for opening a PTY WebSocket connection.",
|
||||
}),
|
||||
|
||||
@@ -13,6 +13,20 @@ const DiffQuery = Schema.Struct({
|
||||
})
|
||||
|
||||
export const VcsGroup = HttpApiGroup.make("server.vcs")
|
||||
.add(
|
||||
HttpApiEndpoint.get("vcs.get", "/api/vcs", {
|
||||
query: LocationQuery,
|
||||
success: Location.response(Vcs.Info),
|
||||
})
|
||||
.annotateMerge(locationQueryOpenApi)
|
||||
.annotateMerge(
|
||||
OpenApi.annotations({
|
||||
identifier: "v2.vcs.get",
|
||||
summary: "VCS information",
|
||||
description: "Get the current and default branches for the requested location.",
|
||||
}),
|
||||
),
|
||||
)
|
||||
.add(
|
||||
HttpApiEndpoint.get("vcs.status", "/api/vcs/status", {
|
||||
query: LocationQuery,
|
||||
|
||||
@@ -16,6 +16,7 @@ export const Info = Schema.Struct({
|
||||
agent: Agent.ID.pipe(optional),
|
||||
model: Model.Ref.pipe(optional),
|
||||
subtask: Schema.Boolean.pipe(optional),
|
||||
source: Schema.Literals(["command", "mcp"]).pipe(optional),
|
||||
}).annotate({ identifier: "Command.Info" })
|
||||
|
||||
export const Event = {
|
||||
|
||||
@@ -14,6 +14,7 @@ export { Model } from "./model.js"
|
||||
export { Money } from "./money.js"
|
||||
export { Permission } from "./permission.js"
|
||||
export { PermissionSaved } from "./permission-saved.js"
|
||||
export { Path } from "./path.js"
|
||||
export { Project } from "./project.js"
|
||||
export { ProjectCopy } from "./project-copy.js"
|
||||
export { Provider } from "./provider.js"
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
export * as Path from "./path.js"
|
||||
|
||||
import { Schema } from "effect"
|
||||
import { AbsolutePath } from "./schema.js"
|
||||
|
||||
export const Info = Schema.Struct({
|
||||
home: AbsolutePath,
|
||||
state: AbsolutePath,
|
||||
config: AbsolutePath,
|
||||
worktree: AbsolutePath,
|
||||
directory: AbsolutePath,
|
||||
}).annotate({ identifier: "Path.Info" })
|
||||
export interface Info extends Schema.Schema.Type<typeof Info> {}
|
||||
@@ -56,3 +56,10 @@ export const UpdateInput = Schema.Struct({
|
||||
),
|
||||
})
|
||||
export interface UpdateInput extends Schema.Schema.Type<typeof UpdateInput> {}
|
||||
|
||||
export const Shell = Schema.Struct({
|
||||
path: Schema.String,
|
||||
name: Schema.String,
|
||||
acceptable: Schema.Boolean,
|
||||
}).annotate({ identifier: "Pty.Shell" })
|
||||
export interface Shell extends Schema.Schema.Type<typeof Shell> {}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
export * as Vcs from "./vcs.js"
|
||||
|
||||
import { Schema } from "effect"
|
||||
import { NonNegativeInt } from "./schema.js"
|
||||
import { NonNegativeInt, optional } from "./schema.js"
|
||||
|
||||
export const Mode = Schema.Literals(["working", "branch"]).annotate({ identifier: "Vcs.Mode" })
|
||||
export type Mode = typeof Mode.Type
|
||||
@@ -13,3 +13,9 @@ export const FileStatus = Schema.Struct({
|
||||
status: Schema.Literals(["added", "deleted", "modified"]),
|
||||
}).annotate({ identifier: "Vcs.FileStatus" })
|
||||
export interface FileStatus extends Schema.Schema.Type<typeof FileStatus> {}
|
||||
|
||||
export const Info = Schema.Struct({
|
||||
branch: optional(Schema.String),
|
||||
defaultBranch: optional(Schema.String),
|
||||
}).annotate({ identifier: "Vcs.Info" })
|
||||
export interface Info extends Schema.Schema.Type<typeof Info> {}
|
||||
|
||||
@@ -26,6 +26,7 @@ import { CredentialHandler } from "./handlers/credential"
|
||||
import { ProjectHandler } from "./handlers/project"
|
||||
import { ProjectCopyHandler } from "./handlers/project-copy"
|
||||
import { VcsHandler } from "./handlers/vcs"
|
||||
import { PathHandler } from "./handlers/path"
|
||||
import { EventFeed } from "./event-feed"
|
||||
|
||||
export const handlers = Layer.mergeAll(
|
||||
@@ -56,4 +57,5 @@ export const handlers = Layer.mergeAll(
|
||||
ReferenceHandler,
|
||||
ProjectCopyHandler,
|
||||
VcsHandler,
|
||||
PathHandler,
|
||||
)
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
import { Location } from "@opencode-ai/core/location"
|
||||
import { AbsolutePath } from "@opencode-ai/core/schema"
|
||||
import { Global } from "@opencode-ai/util/global"
|
||||
import { Effect } from "effect"
|
||||
import { HttpApiBuilder } from "effect/unstable/httpapi"
|
||||
import { Api } from "../api"
|
||||
|
||||
export const PathHandler = HttpApiBuilder.group(Api, "server.path", (handlers) =>
|
||||
handlers.handle("path.get", () =>
|
||||
Effect.gen(function* () {
|
||||
const global = yield* Global.Service
|
||||
const location = yield* Location.Service
|
||||
return {
|
||||
home: AbsolutePath.make(global.home),
|
||||
state: AbsolutePath.make(global.state),
|
||||
config: AbsolutePath.make(global.config),
|
||||
worktree: location.project.directory,
|
||||
directory: location.directory,
|
||||
}
|
||||
}),
|
||||
),
|
||||
)
|
||||
@@ -29,6 +29,13 @@ export const PtyHandler = HttpApiBuilder.group(Api, "server.pty", (handlers) =>
|
||||
const environment = yield* PtyEnvironment.Service
|
||||
|
||||
return handlers
|
||||
.handle(
|
||||
"pty.shells",
|
||||
Effect.fn(function* () {
|
||||
const pty = yield* Pty.Service
|
||||
return yield* response(pty.shells())
|
||||
}),
|
||||
)
|
||||
.handle(
|
||||
"pty.list",
|
||||
Effect.fn(function* () {
|
||||
|
||||
@@ -7,6 +7,14 @@ import { response } from "../location"
|
||||
export const VcsHandler = HttpApiBuilder.group(Api, "server.vcs", (handlers) =>
|
||||
Effect.gen(function* () {
|
||||
return handlers
|
||||
.handle("vcs.get", () =>
|
||||
response(
|
||||
Effect.gen(function* () {
|
||||
const vcs = yield* Vcs.Service
|
||||
return yield* vcs.info()
|
||||
}),
|
||||
),
|
||||
)
|
||||
.handle("vcs.status", () =>
|
||||
response(
|
||||
Effect.gen(function* () {
|
||||
|
||||
@@ -60,6 +60,7 @@ const applicationServices = LayerNode.group([
|
||||
WellKnown.node,
|
||||
PtyEnvironment.node,
|
||||
LocationServiceMap.node,
|
||||
Global.node,
|
||||
SessionRestart.node,
|
||||
])
|
||||
|
||||
@@ -134,7 +135,9 @@ function makeRoutes<AuthError, AuthServices>(
|
||||
Layer.flatMap((context) => {
|
||||
const services = Layer.succeedContext(context)
|
||||
const requestServices = Layer.merge(
|
||||
Layer.succeedContext(Context.pick(PermissionSaved.Service, Project.Service, WellKnown.Service)(context)),
|
||||
Layer.succeedContext(
|
||||
Context.pick(Global.Service, PermissionSaved.Service, Project.Service, WellKnown.Service)(context),
|
||||
),
|
||||
ServerInfo.layer(serviceURLs, options.app),
|
||||
)
|
||||
return HttpApiBuilder.layer(Api, { openapiPath: "/openapi.json" }).pipe(
|
||||
|
||||
Reference in New Issue
Block a user