mirror of
https://github.com/anomalyco/opencode.git
synced 2026-07-10 02:58:29 +00:00
feat(client): expose v2 project APIs (#34456)
This commit is contained in:
parent
01edae4a7f
commit
935ac2db91
23 changed files with 472 additions and 243 deletions
|
|
@ -35,6 +35,7 @@ export const groupNames = {
|
|||
"server.pty": "ptys",
|
||||
"server.question": "questions",
|
||||
"server.reference": "references",
|
||||
"server.project": "project",
|
||||
"server.projectCopy": "projectCopies",
|
||||
} as const
|
||||
|
||||
|
|
|
|||
|
|
@ -410,36 +410,57 @@ const Endpoint9_1 = (raw: RawClient["server.credential"]) => (input: Endpoint9_1
|
|||
|
||||
const adaptGroup9 = (raw: RawClient["server.credential"]) => ({ update: Endpoint9_0(raw), remove: Endpoint9_1(raw) })
|
||||
|
||||
type Endpoint10_0Request = Parameters<RawClient["server.permission"]["permission.request.list"]>[0]
|
||||
type Endpoint10_0Request = Parameters<RawClient["server.project"]["project.current"]>[0]
|
||||
type Endpoint10_0Input = { readonly location?: Endpoint10_0Request["query"]["location"] }
|
||||
const Endpoint10_0 = (raw: RawClient["server.permission"]) => (input?: Endpoint10_0Input) =>
|
||||
const Endpoint10_0 = (raw: RawClient["server.project"]) => (input?: Endpoint10_0Input) =>
|
||||
raw["project.current"]({ query: { location: input?.["location"] } }).pipe(Effect.mapError(mapClientError))
|
||||
|
||||
type Endpoint10_1Request = Parameters<RawClient["server.project"]["project.directories"]>[0]
|
||||
type Endpoint10_1Input = {
|
||||
readonly projectID: Endpoint10_1Request["params"]["projectID"]
|
||||
readonly location?: Endpoint10_1Request["query"]["location"]
|
||||
}
|
||||
const Endpoint10_1 = (raw: RawClient["server.project"]) => (input: Endpoint10_1Input) =>
|
||||
raw["project.directories"]({
|
||||
params: { projectID: input["projectID"] },
|
||||
query: { location: input["location"] },
|
||||
}).pipe(Effect.mapError(mapClientError))
|
||||
|
||||
const adaptGroup10 = (raw: RawClient["server.project"]) => ({
|
||||
current: Endpoint10_0(raw),
|
||||
directories: Endpoint10_1(raw),
|
||||
})
|
||||
|
||||
type Endpoint11_0Request = Parameters<RawClient["server.permission"]["permission.request.list"]>[0]
|
||||
type Endpoint11_0Input = { readonly location?: Endpoint11_0Request["query"]["location"] }
|
||||
const Endpoint11_0 = (raw: RawClient["server.permission"]) => (input?: Endpoint11_0Input) =>
|
||||
raw["permission.request.list"]({ query: { location: input?.["location"] } }).pipe(Effect.mapError(mapClientError))
|
||||
|
||||
type Endpoint10_1Request = Parameters<RawClient["server.permission"]["permission.saved.list"]>[0]
|
||||
type Endpoint10_1Input = { readonly projectID?: Endpoint10_1Request["query"]["projectID"] }
|
||||
const Endpoint10_1 = (raw: RawClient["server.permission"]) => (input?: Endpoint10_1Input) =>
|
||||
type Endpoint11_1Request = Parameters<RawClient["server.permission"]["permission.saved.list"]>[0]
|
||||
type Endpoint11_1Input = { readonly projectID?: Endpoint11_1Request["query"]["projectID"] }
|
||||
const Endpoint11_1 = (raw: RawClient["server.permission"]) => (input?: Endpoint11_1Input) =>
|
||||
raw["permission.saved.list"]({ query: { projectID: input?.["projectID"] } }).pipe(
|
||||
Effect.mapError(mapClientError),
|
||||
Effect.map((value) => value.data),
|
||||
)
|
||||
|
||||
type Endpoint10_2Request = Parameters<RawClient["server.permission"]["permission.saved.remove"]>[0]
|
||||
type Endpoint10_2Input = { readonly id: Endpoint10_2Request["params"]["id"] }
|
||||
const Endpoint10_2 = (raw: RawClient["server.permission"]) => (input: Endpoint10_2Input) =>
|
||||
type Endpoint11_2Request = Parameters<RawClient["server.permission"]["permission.saved.remove"]>[0]
|
||||
type Endpoint11_2Input = { readonly id: Endpoint11_2Request["params"]["id"] }
|
||||
const Endpoint11_2 = (raw: RawClient["server.permission"]) => (input: Endpoint11_2Input) =>
|
||||
raw["permission.saved.remove"]({ params: { id: input["id"] } }).pipe(Effect.mapError(mapClientError))
|
||||
|
||||
type Endpoint10_3Request = Parameters<RawClient["server.permission"]["session.permission.create"]>[0]
|
||||
type Endpoint10_3Input = {
|
||||
readonly sessionID: Endpoint10_3Request["params"]["sessionID"]
|
||||
readonly id?: Endpoint10_3Request["payload"]["id"]
|
||||
readonly action: Endpoint10_3Request["payload"]["action"]
|
||||
readonly resources: Endpoint10_3Request["payload"]["resources"]
|
||||
readonly save?: Endpoint10_3Request["payload"]["save"]
|
||||
readonly metadata?: Endpoint10_3Request["payload"]["metadata"]
|
||||
readonly source?: Endpoint10_3Request["payload"]["source"]
|
||||
readonly agent?: Endpoint10_3Request["payload"]["agent"]
|
||||
type Endpoint11_3Request = Parameters<RawClient["server.permission"]["session.permission.create"]>[0]
|
||||
type Endpoint11_3Input = {
|
||||
readonly sessionID: Endpoint11_3Request["params"]["sessionID"]
|
||||
readonly id?: Endpoint11_3Request["payload"]["id"]
|
||||
readonly action: Endpoint11_3Request["payload"]["action"]
|
||||
readonly resources: Endpoint11_3Request["payload"]["resources"]
|
||||
readonly save?: Endpoint11_3Request["payload"]["save"]
|
||||
readonly metadata?: Endpoint11_3Request["payload"]["metadata"]
|
||||
readonly source?: Endpoint11_3Request["payload"]["source"]
|
||||
readonly agent?: Endpoint11_3Request["payload"]["agent"]
|
||||
}
|
||||
const Endpoint10_3 = (raw: RawClient["server.permission"]) => (input: Endpoint10_3Input) =>
|
||||
const Endpoint11_3 = (raw: RawClient["server.permission"]) => (input: Endpoint11_3Input) =>
|
||||
raw["session.permission.create"]({
|
||||
params: { sessionID: input["sessionID"] },
|
||||
payload: {
|
||||
|
|
@ -456,87 +477,87 @@ const Endpoint10_3 = (raw: RawClient["server.permission"]) => (input: Endpoint10
|
|||
Effect.map((value) => value.data),
|
||||
)
|
||||
|
||||
type Endpoint10_4Request = Parameters<RawClient["server.permission"]["session.permission.list"]>[0]
|
||||
type Endpoint10_4Input = { readonly sessionID: Endpoint10_4Request["params"]["sessionID"] }
|
||||
const Endpoint10_4 = (raw: RawClient["server.permission"]) => (input: Endpoint10_4Input) =>
|
||||
type Endpoint11_4Request = Parameters<RawClient["server.permission"]["session.permission.list"]>[0]
|
||||
type Endpoint11_4Input = { readonly sessionID: Endpoint11_4Request["params"]["sessionID"] }
|
||||
const Endpoint11_4 = (raw: RawClient["server.permission"]) => (input: Endpoint11_4Input) =>
|
||||
raw["session.permission.list"]({ params: { sessionID: input["sessionID"] } }).pipe(
|
||||
Effect.mapError(mapClientError),
|
||||
Effect.map((value) => value.data),
|
||||
)
|
||||
|
||||
type Endpoint10_5Request = Parameters<RawClient["server.permission"]["session.permission.get"]>[0]
|
||||
type Endpoint10_5Input = {
|
||||
readonly sessionID: Endpoint10_5Request["params"]["sessionID"]
|
||||
readonly requestID: Endpoint10_5Request["params"]["requestID"]
|
||||
type Endpoint11_5Request = Parameters<RawClient["server.permission"]["session.permission.get"]>[0]
|
||||
type Endpoint11_5Input = {
|
||||
readonly sessionID: Endpoint11_5Request["params"]["sessionID"]
|
||||
readonly requestID: Endpoint11_5Request["params"]["requestID"]
|
||||
}
|
||||
const Endpoint10_5 = (raw: RawClient["server.permission"]) => (input: Endpoint10_5Input) =>
|
||||
const Endpoint11_5 = (raw: RawClient["server.permission"]) => (input: Endpoint11_5Input) =>
|
||||
raw["session.permission.get"]({ params: { sessionID: input["sessionID"], requestID: input["requestID"] } }).pipe(
|
||||
Effect.mapError(mapClientError),
|
||||
Effect.map((value) => value.data),
|
||||
)
|
||||
|
||||
type Endpoint10_6Request = Parameters<RawClient["server.permission"]["session.permission.reply"]>[0]
|
||||
type Endpoint10_6Input = {
|
||||
readonly sessionID: Endpoint10_6Request["params"]["sessionID"]
|
||||
readonly requestID: Endpoint10_6Request["params"]["requestID"]
|
||||
readonly reply: Endpoint10_6Request["payload"]["reply"]
|
||||
readonly message?: Endpoint10_6Request["payload"]["message"]
|
||||
type Endpoint11_6Request = Parameters<RawClient["server.permission"]["session.permission.reply"]>[0]
|
||||
type Endpoint11_6Input = {
|
||||
readonly sessionID: Endpoint11_6Request["params"]["sessionID"]
|
||||
readonly requestID: Endpoint11_6Request["params"]["requestID"]
|
||||
readonly reply: Endpoint11_6Request["payload"]["reply"]
|
||||
readonly message?: Endpoint11_6Request["payload"]["message"]
|
||||
}
|
||||
const Endpoint10_6 = (raw: RawClient["server.permission"]) => (input: Endpoint10_6Input) =>
|
||||
const Endpoint11_6 = (raw: RawClient["server.permission"]) => (input: Endpoint11_6Input) =>
|
||||
raw["session.permission.reply"]({
|
||||
params: { sessionID: input["sessionID"], requestID: input["requestID"] },
|
||||
payload: { reply: input["reply"], message: input["message"] },
|
||||
}).pipe(Effect.mapError(mapClientError))
|
||||
|
||||
const adaptGroup10 = (raw: RawClient["server.permission"]) => ({
|
||||
listRequests: Endpoint10_0(raw),
|
||||
listSaved: Endpoint10_1(raw),
|
||||
removeSaved: Endpoint10_2(raw),
|
||||
create: Endpoint10_3(raw),
|
||||
list: Endpoint10_4(raw),
|
||||
get: Endpoint10_5(raw),
|
||||
reply: Endpoint10_6(raw),
|
||||
const adaptGroup11 = (raw: RawClient["server.permission"]) => ({
|
||||
listRequests: Endpoint11_0(raw),
|
||||
listSaved: Endpoint11_1(raw),
|
||||
removeSaved: Endpoint11_2(raw),
|
||||
create: Endpoint11_3(raw),
|
||||
list: Endpoint11_4(raw),
|
||||
get: Endpoint11_5(raw),
|
||||
reply: Endpoint11_6(raw),
|
||||
})
|
||||
|
||||
type Endpoint11_0Request = Parameters<RawClient["server.fs"]["fs.list"]>[0]
|
||||
type Endpoint11_0Input = {
|
||||
readonly location?: Endpoint11_0Request["query"]["location"]
|
||||
readonly path?: Endpoint11_0Request["query"]["path"]
|
||||
type Endpoint12_0Request = Parameters<RawClient["server.fs"]["fs.list"]>[0]
|
||||
type Endpoint12_0Input = {
|
||||
readonly location?: Endpoint12_0Request["query"]["location"]
|
||||
readonly path?: Endpoint12_0Request["query"]["path"]
|
||||
}
|
||||
const Endpoint11_0 = (raw: RawClient["server.fs"]) => (input?: Endpoint11_0Input) =>
|
||||
const Endpoint12_0 = (raw: RawClient["server.fs"]) => (input?: Endpoint12_0Input) =>
|
||||
raw["fs.list"]({ query: { location: input?.["location"], path: input?.["path"] } }).pipe(
|
||||
Effect.mapError(mapClientError),
|
||||
)
|
||||
|
||||
type Endpoint11_1Request = Parameters<RawClient["server.fs"]["fs.find"]>[0]
|
||||
type Endpoint11_1Input = {
|
||||
readonly location?: Endpoint11_1Request["query"]["location"]
|
||||
readonly query: Endpoint11_1Request["query"]["query"]
|
||||
readonly type?: Endpoint11_1Request["query"]["type"]
|
||||
readonly limit?: Endpoint11_1Request["query"]["limit"]
|
||||
type Endpoint12_1Request = Parameters<RawClient["server.fs"]["fs.find"]>[0]
|
||||
type Endpoint12_1Input = {
|
||||
readonly location?: Endpoint12_1Request["query"]["location"]
|
||||
readonly query: Endpoint12_1Request["query"]["query"]
|
||||
readonly type?: Endpoint12_1Request["query"]["type"]
|
||||
readonly limit?: Endpoint12_1Request["query"]["limit"]
|
||||
}
|
||||
const Endpoint11_1 = (raw: RawClient["server.fs"]) => (input: Endpoint11_1Input) =>
|
||||
const Endpoint12_1 = (raw: RawClient["server.fs"]) => (input: Endpoint12_1Input) =>
|
||||
raw["fs.find"]({
|
||||
query: { location: input["location"], query: input["query"], type: input["type"], limit: input["limit"] },
|
||||
}).pipe(Effect.mapError(mapClientError))
|
||||
|
||||
const adaptGroup11 = (raw: RawClient["server.fs"]) => ({ list: Endpoint11_0(raw), find: Endpoint11_1(raw) })
|
||||
const adaptGroup12 = (raw: RawClient["server.fs"]) => ({ list: Endpoint12_0(raw), find: Endpoint12_1(raw) })
|
||||
|
||||
type Endpoint12_0Request = Parameters<RawClient["server.command"]["command.list"]>[0]
|
||||
type Endpoint12_0Input = { readonly location?: Endpoint12_0Request["query"]["location"] }
|
||||
const Endpoint12_0 = (raw: RawClient["server.command"]) => (input?: Endpoint12_0Input) =>
|
||||
type Endpoint13_0Request = Parameters<RawClient["server.command"]["command.list"]>[0]
|
||||
type Endpoint13_0Input = { readonly location?: Endpoint13_0Request["query"]["location"] }
|
||||
const Endpoint13_0 = (raw: RawClient["server.command"]) => (input?: Endpoint13_0Input) =>
|
||||
raw["command.list"]({ query: { location: input?.["location"] } }).pipe(Effect.mapError(mapClientError))
|
||||
|
||||
const adaptGroup12 = (raw: RawClient["server.command"]) => ({ list: Endpoint12_0(raw) })
|
||||
const adaptGroup13 = (raw: RawClient["server.command"]) => ({ list: Endpoint13_0(raw) })
|
||||
|
||||
type Endpoint13_0Request = Parameters<RawClient["server.skill"]["skill.list"]>[0]
|
||||
type Endpoint13_0Input = { readonly location?: Endpoint13_0Request["query"]["location"] }
|
||||
const Endpoint13_0 = (raw: RawClient["server.skill"]) => (input?: Endpoint13_0Input) =>
|
||||
type Endpoint14_0Request = Parameters<RawClient["server.skill"]["skill.list"]>[0]
|
||||
type Endpoint14_0Input = { readonly location?: Endpoint14_0Request["query"]["location"] }
|
||||
const Endpoint14_0 = (raw: RawClient["server.skill"]) => (input?: Endpoint14_0Input) =>
|
||||
raw["skill.list"]({ query: { location: input?.["location"] } }).pipe(Effect.mapError(mapClientError))
|
||||
|
||||
const adaptGroup13 = (raw: RawClient["server.skill"]) => ({ list: Endpoint13_0(raw) })
|
||||
const adaptGroup14 = (raw: RawClient["server.skill"]) => ({ list: Endpoint14_0(raw) })
|
||||
|
||||
const Endpoint14_0 = (raw: RawClient["server.event"]) => () =>
|
||||
const Endpoint15_0 = (raw: RawClient["server.event"]) => () =>
|
||||
Stream.unwrap(
|
||||
raw["event.subscribe"]({}).pipe(
|
||||
Effect.mapError(mapClientError),
|
||||
|
|
@ -544,23 +565,23 @@ const Endpoint14_0 = (raw: RawClient["server.event"]) => () =>
|
|||
),
|
||||
)
|
||||
|
||||
const adaptGroup14 = (raw: RawClient["server.event"]) => ({ subscribe: Endpoint14_0(raw) })
|
||||
const adaptGroup15 = (raw: RawClient["server.event"]) => ({ subscribe: Endpoint15_0(raw) })
|
||||
|
||||
type Endpoint15_0Request = Parameters<RawClient["server.pty"]["pty.list"]>[0]
|
||||
type Endpoint15_0Input = { readonly location?: Endpoint15_0Request["query"]["location"] }
|
||||
const Endpoint15_0 = (raw: RawClient["server.pty"]) => (input?: Endpoint15_0Input) =>
|
||||
type Endpoint16_0Request = Parameters<RawClient["server.pty"]["pty.list"]>[0]
|
||||
type Endpoint16_0Input = { readonly location?: Endpoint16_0Request["query"]["location"] }
|
||||
const Endpoint16_0 = (raw: RawClient["server.pty"]) => (input?: Endpoint16_0Input) =>
|
||||
raw["pty.list"]({ query: { location: input?.["location"] } }).pipe(Effect.mapError(mapClientError))
|
||||
|
||||
type Endpoint15_1Request = Parameters<RawClient["server.pty"]["pty.create"]>[0]
|
||||
type Endpoint15_1Input = {
|
||||
readonly location?: Endpoint15_1Request["query"]["location"]
|
||||
readonly command?: Endpoint15_1Request["payload"]["command"]
|
||||
readonly args?: Endpoint15_1Request["payload"]["args"]
|
||||
readonly cwd?: Endpoint15_1Request["payload"]["cwd"]
|
||||
readonly title?: Endpoint15_1Request["payload"]["title"]
|
||||
readonly env?: Endpoint15_1Request["payload"]["env"]
|
||||
type Endpoint16_1Request = Parameters<RawClient["server.pty"]["pty.create"]>[0]
|
||||
type Endpoint16_1Input = {
|
||||
readonly location?: Endpoint16_1Request["query"]["location"]
|
||||
readonly command?: Endpoint16_1Request["payload"]["command"]
|
||||
readonly args?: Endpoint16_1Request["payload"]["args"]
|
||||
readonly cwd?: Endpoint16_1Request["payload"]["cwd"]
|
||||
readonly title?: Endpoint16_1Request["payload"]["title"]
|
||||
readonly env?: Endpoint16_1Request["payload"]["env"]
|
||||
}
|
||||
const Endpoint15_1 = (raw: RawClient["server.pty"]) => (input?: Endpoint15_1Input) =>
|
||||
const Endpoint16_1 = (raw: RawClient["server.pty"]) => (input?: Endpoint16_1Input) =>
|
||||
raw["pty.create"]({
|
||||
query: { location: input?.["location"] },
|
||||
payload: {
|
||||
|
|
@ -572,201 +593,201 @@ const Endpoint15_1 = (raw: RawClient["server.pty"]) => (input?: Endpoint15_1Inpu
|
|||
},
|
||||
}).pipe(Effect.mapError(mapClientError))
|
||||
|
||||
type Endpoint15_2Request = Parameters<RawClient["server.pty"]["pty.get"]>[0]
|
||||
type Endpoint15_2Input = {
|
||||
readonly ptyID: Endpoint15_2Request["params"]["ptyID"]
|
||||
readonly location?: Endpoint15_2Request["query"]["location"]
|
||||
type Endpoint16_2Request = Parameters<RawClient["server.pty"]["pty.get"]>[0]
|
||||
type Endpoint16_2Input = {
|
||||
readonly ptyID: Endpoint16_2Request["params"]["ptyID"]
|
||||
readonly location?: Endpoint16_2Request["query"]["location"]
|
||||
}
|
||||
const Endpoint15_2 = (raw: RawClient["server.pty"]) => (input: Endpoint15_2Input) =>
|
||||
const Endpoint16_2 = (raw: RawClient["server.pty"]) => (input: Endpoint16_2Input) =>
|
||||
raw["pty.get"]({ params: { ptyID: input["ptyID"] }, query: { location: input["location"] } }).pipe(
|
||||
Effect.mapError(mapClientError),
|
||||
)
|
||||
|
||||
type Endpoint15_3Request = Parameters<RawClient["server.pty"]["pty.update"]>[0]
|
||||
type Endpoint15_3Input = {
|
||||
readonly ptyID: Endpoint15_3Request["params"]["ptyID"]
|
||||
readonly location?: Endpoint15_3Request["query"]["location"]
|
||||
readonly title?: Endpoint15_3Request["payload"]["title"]
|
||||
readonly size?: Endpoint15_3Request["payload"]["size"]
|
||||
type Endpoint16_3Request = Parameters<RawClient["server.pty"]["pty.update"]>[0]
|
||||
type Endpoint16_3Input = {
|
||||
readonly ptyID: Endpoint16_3Request["params"]["ptyID"]
|
||||
readonly location?: Endpoint16_3Request["query"]["location"]
|
||||
readonly title?: Endpoint16_3Request["payload"]["title"]
|
||||
readonly size?: Endpoint16_3Request["payload"]["size"]
|
||||
}
|
||||
const Endpoint15_3 = (raw: RawClient["server.pty"]) => (input: Endpoint15_3Input) =>
|
||||
const Endpoint16_3 = (raw: RawClient["server.pty"]) => (input: Endpoint16_3Input) =>
|
||||
raw["pty.update"]({
|
||||
params: { ptyID: input["ptyID"] },
|
||||
query: { location: input["location"] },
|
||||
payload: { title: input["title"], size: input["size"] },
|
||||
}).pipe(Effect.mapError(mapClientError))
|
||||
|
||||
type Endpoint15_4Request = Parameters<RawClient["server.pty"]["pty.remove"]>[0]
|
||||
type Endpoint15_4Input = {
|
||||
readonly ptyID: Endpoint15_4Request["params"]["ptyID"]
|
||||
readonly location?: Endpoint15_4Request["query"]["location"]
|
||||
type Endpoint16_4Request = Parameters<RawClient["server.pty"]["pty.remove"]>[0]
|
||||
type Endpoint16_4Input = {
|
||||
readonly ptyID: Endpoint16_4Request["params"]["ptyID"]
|
||||
readonly location?: Endpoint16_4Request["query"]["location"]
|
||||
}
|
||||
const Endpoint15_4 = (raw: RawClient["server.pty"]) => (input: Endpoint15_4Input) =>
|
||||
const Endpoint16_4 = (raw: RawClient["server.pty"]) => (input: Endpoint16_4Input) =>
|
||||
raw["pty.remove"]({ params: { ptyID: input["ptyID"] }, query: { location: input["location"] } }).pipe(
|
||||
Effect.mapError(mapClientError),
|
||||
)
|
||||
|
||||
const adaptGroup15 = (raw: RawClient["server.pty"]) => ({
|
||||
list: Endpoint15_0(raw),
|
||||
create: Endpoint15_1(raw),
|
||||
get: Endpoint15_2(raw),
|
||||
update: Endpoint15_3(raw),
|
||||
remove: Endpoint15_4(raw),
|
||||
const adaptGroup16 = (raw: RawClient["server.pty"]) => ({
|
||||
list: Endpoint16_0(raw),
|
||||
create: Endpoint16_1(raw),
|
||||
get: Endpoint16_2(raw),
|
||||
update: Endpoint16_3(raw),
|
||||
remove: Endpoint16_4(raw),
|
||||
})
|
||||
|
||||
type Endpoint16_0Request = Parameters<RawClient["server.shell"]["shell.list"]>[0]
|
||||
type Endpoint16_0Input = { readonly location?: Endpoint16_0Request["query"]["location"] }
|
||||
const Endpoint16_0 = (raw: RawClient["server.shell"]) => (input?: Endpoint16_0Input) =>
|
||||
type Endpoint17_0Request = Parameters<RawClient["server.shell"]["shell.list"]>[0]
|
||||
type Endpoint17_0Input = { readonly location?: Endpoint17_0Request["query"]["location"] }
|
||||
const Endpoint17_0 = (raw: RawClient["server.shell"]) => (input?: Endpoint17_0Input) =>
|
||||
raw["shell.list"]({ query: { location: input?.["location"] } }).pipe(Effect.mapError(mapClientError))
|
||||
|
||||
type Endpoint16_1Request = Parameters<RawClient["server.shell"]["shell.create"]>[0]
|
||||
type Endpoint16_1Input = {
|
||||
readonly location?: Endpoint16_1Request["query"]["location"]
|
||||
readonly command: Endpoint16_1Request["payload"]["command"]
|
||||
readonly cwd?: Endpoint16_1Request["payload"]["cwd"]
|
||||
readonly timeout?: Endpoint16_1Request["payload"]["timeout"]
|
||||
readonly metadata?: Endpoint16_1Request["payload"]["metadata"]
|
||||
type Endpoint17_1Request = Parameters<RawClient["server.shell"]["shell.create"]>[0]
|
||||
type Endpoint17_1Input = {
|
||||
readonly location?: Endpoint17_1Request["query"]["location"]
|
||||
readonly command: Endpoint17_1Request["payload"]["command"]
|
||||
readonly cwd?: Endpoint17_1Request["payload"]["cwd"]
|
||||
readonly timeout?: Endpoint17_1Request["payload"]["timeout"]
|
||||
readonly metadata?: Endpoint17_1Request["payload"]["metadata"]
|
||||
}
|
||||
const Endpoint16_1 = (raw: RawClient["server.shell"]) => (input: Endpoint16_1Input) =>
|
||||
const Endpoint17_1 = (raw: RawClient["server.shell"]) => (input: Endpoint17_1Input) =>
|
||||
raw["shell.create"]({
|
||||
query: { location: input["location"] },
|
||||
payload: { command: input["command"], cwd: input["cwd"], timeout: input["timeout"], metadata: input["metadata"] },
|
||||
}).pipe(Effect.mapError(mapClientError))
|
||||
|
||||
type Endpoint16_2Request = Parameters<RawClient["server.shell"]["shell.get"]>[0]
|
||||
type Endpoint16_2Input = {
|
||||
readonly id: Endpoint16_2Request["params"]["id"]
|
||||
readonly location?: Endpoint16_2Request["query"]["location"]
|
||||
type Endpoint17_2Request = Parameters<RawClient["server.shell"]["shell.get"]>[0]
|
||||
type Endpoint17_2Input = {
|
||||
readonly id: Endpoint17_2Request["params"]["id"]
|
||||
readonly location?: Endpoint17_2Request["query"]["location"]
|
||||
}
|
||||
const Endpoint16_2 = (raw: RawClient["server.shell"]) => (input: Endpoint16_2Input) =>
|
||||
const Endpoint17_2 = (raw: RawClient["server.shell"]) => (input: Endpoint17_2Input) =>
|
||||
raw["shell.get"]({ params: { id: input["id"] }, query: { location: input["location"] } }).pipe(
|
||||
Effect.mapError(mapClientError),
|
||||
)
|
||||
|
||||
type Endpoint16_3Request = Parameters<RawClient["server.shell"]["shell.output"]>[0]
|
||||
type Endpoint16_3Input = {
|
||||
readonly id: Endpoint16_3Request["params"]["id"]
|
||||
readonly location?: Endpoint16_3Request["query"]["location"]
|
||||
readonly cursor?: Endpoint16_3Request["query"]["cursor"]
|
||||
readonly limit?: Endpoint16_3Request["query"]["limit"]
|
||||
type Endpoint17_3Request = Parameters<RawClient["server.shell"]["shell.output"]>[0]
|
||||
type Endpoint17_3Input = {
|
||||
readonly id: Endpoint17_3Request["params"]["id"]
|
||||
readonly location?: Endpoint17_3Request["query"]["location"]
|
||||
readonly cursor?: Endpoint17_3Request["query"]["cursor"]
|
||||
readonly limit?: Endpoint17_3Request["query"]["limit"]
|
||||
}
|
||||
const Endpoint16_3 = (raw: RawClient["server.shell"]) => (input: Endpoint16_3Input) =>
|
||||
const Endpoint17_3 = (raw: RawClient["server.shell"]) => (input: Endpoint17_3Input) =>
|
||||
raw["shell.output"]({
|
||||
params: { id: input["id"] },
|
||||
query: { location: input["location"], cursor: input["cursor"], limit: input["limit"] },
|
||||
}).pipe(Effect.mapError(mapClientError))
|
||||
|
||||
type Endpoint16_4Request = Parameters<RawClient["server.shell"]["shell.remove"]>[0]
|
||||
type Endpoint16_4Input = {
|
||||
readonly id: Endpoint16_4Request["params"]["id"]
|
||||
readonly location?: Endpoint16_4Request["query"]["location"]
|
||||
type Endpoint17_4Request = Parameters<RawClient["server.shell"]["shell.remove"]>[0]
|
||||
type Endpoint17_4Input = {
|
||||
readonly id: Endpoint17_4Request["params"]["id"]
|
||||
readonly location?: Endpoint17_4Request["query"]["location"]
|
||||
}
|
||||
const Endpoint16_4 = (raw: RawClient["server.shell"]) => (input: Endpoint16_4Input) =>
|
||||
const Endpoint17_4 = (raw: RawClient["server.shell"]) => (input: Endpoint17_4Input) =>
|
||||
raw["shell.remove"]({ params: { id: input["id"] }, query: { location: input["location"] } }).pipe(
|
||||
Effect.mapError(mapClientError),
|
||||
)
|
||||
|
||||
const adaptGroup16 = (raw: RawClient["server.shell"]) => ({
|
||||
list: Endpoint16_0(raw),
|
||||
create: Endpoint16_1(raw),
|
||||
get: Endpoint16_2(raw),
|
||||
output: Endpoint16_3(raw),
|
||||
remove: Endpoint16_4(raw),
|
||||
const adaptGroup17 = (raw: RawClient["server.shell"]) => ({
|
||||
list: Endpoint17_0(raw),
|
||||
create: Endpoint17_1(raw),
|
||||
get: Endpoint17_2(raw),
|
||||
output: Endpoint17_3(raw),
|
||||
remove: Endpoint17_4(raw),
|
||||
})
|
||||
|
||||
type Endpoint17_0Request = Parameters<RawClient["server.question"]["question.request.list"]>[0]
|
||||
type Endpoint17_0Input = { readonly location?: Endpoint17_0Request["query"]["location"] }
|
||||
const Endpoint17_0 = (raw: RawClient["server.question"]) => (input?: Endpoint17_0Input) =>
|
||||
type Endpoint18_0Request = Parameters<RawClient["server.question"]["question.request.list"]>[0]
|
||||
type Endpoint18_0Input = { readonly location?: Endpoint18_0Request["query"]["location"] }
|
||||
const Endpoint18_0 = (raw: RawClient["server.question"]) => (input?: Endpoint18_0Input) =>
|
||||
raw["question.request.list"]({ query: { location: input?.["location"] } }).pipe(Effect.mapError(mapClientError))
|
||||
|
||||
type Endpoint17_1Request = Parameters<RawClient["server.question"]["session.question.list"]>[0]
|
||||
type Endpoint17_1Input = { readonly sessionID: Endpoint17_1Request["params"]["sessionID"] }
|
||||
const Endpoint17_1 = (raw: RawClient["server.question"]) => (input: Endpoint17_1Input) =>
|
||||
type Endpoint18_1Request = Parameters<RawClient["server.question"]["session.question.list"]>[0]
|
||||
type Endpoint18_1Input = { readonly sessionID: Endpoint18_1Request["params"]["sessionID"] }
|
||||
const Endpoint18_1 = (raw: RawClient["server.question"]) => (input: Endpoint18_1Input) =>
|
||||
raw["session.question.list"]({ params: { sessionID: input["sessionID"] } }).pipe(
|
||||
Effect.mapError(mapClientError),
|
||||
Effect.map((value) => value.data),
|
||||
)
|
||||
|
||||
type Endpoint17_2Request = Parameters<RawClient["server.question"]["session.question.reply"]>[0]
|
||||
type Endpoint17_2Input = {
|
||||
readonly sessionID: Endpoint17_2Request["params"]["sessionID"]
|
||||
readonly requestID: Endpoint17_2Request["params"]["requestID"]
|
||||
readonly answers: Endpoint17_2Request["payload"]["answers"]
|
||||
type Endpoint18_2Request = Parameters<RawClient["server.question"]["session.question.reply"]>[0]
|
||||
type Endpoint18_2Input = {
|
||||
readonly sessionID: Endpoint18_2Request["params"]["sessionID"]
|
||||
readonly requestID: Endpoint18_2Request["params"]["requestID"]
|
||||
readonly answers: Endpoint18_2Request["payload"]["answers"]
|
||||
}
|
||||
const Endpoint17_2 = (raw: RawClient["server.question"]) => (input: Endpoint17_2Input) =>
|
||||
const Endpoint18_2 = (raw: RawClient["server.question"]) => (input: Endpoint18_2Input) =>
|
||||
raw["session.question.reply"]({
|
||||
params: { sessionID: input["sessionID"], requestID: input["requestID"] },
|
||||
payload: { answers: input["answers"] },
|
||||
}).pipe(Effect.mapError(mapClientError))
|
||||
|
||||
type Endpoint17_3Request = Parameters<RawClient["server.question"]["session.question.reject"]>[0]
|
||||
type Endpoint17_3Input = {
|
||||
readonly sessionID: Endpoint17_3Request["params"]["sessionID"]
|
||||
readonly requestID: Endpoint17_3Request["params"]["requestID"]
|
||||
type Endpoint18_3Request = Parameters<RawClient["server.question"]["session.question.reject"]>[0]
|
||||
type Endpoint18_3Input = {
|
||||
readonly sessionID: Endpoint18_3Request["params"]["sessionID"]
|
||||
readonly requestID: Endpoint18_3Request["params"]["requestID"]
|
||||
}
|
||||
const Endpoint17_3 = (raw: RawClient["server.question"]) => (input: Endpoint17_3Input) =>
|
||||
const Endpoint18_3 = (raw: RawClient["server.question"]) => (input: Endpoint18_3Input) =>
|
||||
raw["session.question.reject"]({ params: { sessionID: input["sessionID"], requestID: input["requestID"] } }).pipe(
|
||||
Effect.mapError(mapClientError),
|
||||
)
|
||||
|
||||
const adaptGroup17 = (raw: RawClient["server.question"]) => ({
|
||||
listRequests: Endpoint17_0(raw),
|
||||
list: Endpoint17_1(raw),
|
||||
reply: Endpoint17_2(raw),
|
||||
reject: Endpoint17_3(raw),
|
||||
const adaptGroup18 = (raw: RawClient["server.question"]) => ({
|
||||
listRequests: Endpoint18_0(raw),
|
||||
list: Endpoint18_1(raw),
|
||||
reply: Endpoint18_2(raw),
|
||||
reject: Endpoint18_3(raw),
|
||||
})
|
||||
|
||||
type Endpoint18_0Request = Parameters<RawClient["server.reference"]["reference.list"]>[0]
|
||||
type Endpoint18_0Input = { readonly location?: Endpoint18_0Request["query"]["location"] }
|
||||
const Endpoint18_0 = (raw: RawClient["server.reference"]) => (input?: Endpoint18_0Input) =>
|
||||
type Endpoint19_0Request = Parameters<RawClient["server.reference"]["reference.list"]>[0]
|
||||
type Endpoint19_0Input = { readonly location?: Endpoint19_0Request["query"]["location"] }
|
||||
const Endpoint19_0 = (raw: RawClient["server.reference"]) => (input?: Endpoint19_0Input) =>
|
||||
raw["reference.list"]({ query: { location: input?.["location"] } }).pipe(Effect.mapError(mapClientError))
|
||||
|
||||
const adaptGroup18 = (raw: RawClient["server.reference"]) => ({ list: Endpoint18_0(raw) })
|
||||
const adaptGroup19 = (raw: RawClient["server.reference"]) => ({ list: Endpoint19_0(raw) })
|
||||
|
||||
type Endpoint19_0Request = Parameters<RawClient["server.projectCopy"]["projectCopy.create"]>[0]
|
||||
type Endpoint19_0Input = {
|
||||
readonly projectID: Endpoint19_0Request["params"]["projectID"]
|
||||
readonly location?: Endpoint19_0Request["query"]["location"]
|
||||
readonly strategy: Endpoint19_0Request["payload"]["strategy"]
|
||||
readonly directory: Endpoint19_0Request["payload"]["directory"]
|
||||
readonly name?: Endpoint19_0Request["payload"]["name"]
|
||||
type Endpoint20_0Request = Parameters<RawClient["server.projectCopy"]["projectCopy.create"]>[0]
|
||||
type Endpoint20_0Input = {
|
||||
readonly projectID: Endpoint20_0Request["params"]["projectID"]
|
||||
readonly location?: Endpoint20_0Request["query"]["location"]
|
||||
readonly strategy: Endpoint20_0Request["payload"]["strategy"]
|
||||
readonly directory: Endpoint20_0Request["payload"]["directory"]
|
||||
readonly name?: Endpoint20_0Request["payload"]["name"]
|
||||
}
|
||||
const Endpoint19_0 = (raw: RawClient["server.projectCopy"]) => (input: Endpoint19_0Input) =>
|
||||
const Endpoint20_0 = (raw: RawClient["server.projectCopy"]) => (input: Endpoint20_0Input) =>
|
||||
raw["projectCopy.create"]({
|
||||
params: { projectID: input["projectID"] },
|
||||
query: { location: input["location"] },
|
||||
payload: { strategy: input["strategy"], directory: input["directory"], name: input["name"] },
|
||||
}).pipe(Effect.mapError(mapClientError))
|
||||
|
||||
type Endpoint19_1Request = Parameters<RawClient["server.projectCopy"]["projectCopy.remove"]>[0]
|
||||
type Endpoint19_1Input = {
|
||||
readonly projectID: Endpoint19_1Request["params"]["projectID"]
|
||||
readonly location?: Endpoint19_1Request["query"]["location"]
|
||||
readonly directory: Endpoint19_1Request["payload"]["directory"]
|
||||
readonly force: Endpoint19_1Request["payload"]["force"]
|
||||
type Endpoint20_1Request = Parameters<RawClient["server.projectCopy"]["projectCopy.remove"]>[0]
|
||||
type Endpoint20_1Input = {
|
||||
readonly projectID: Endpoint20_1Request["params"]["projectID"]
|
||||
readonly location?: Endpoint20_1Request["query"]["location"]
|
||||
readonly directory: Endpoint20_1Request["payload"]["directory"]
|
||||
readonly force: Endpoint20_1Request["payload"]["force"]
|
||||
}
|
||||
const Endpoint19_1 = (raw: RawClient["server.projectCopy"]) => (input: Endpoint19_1Input) =>
|
||||
const Endpoint20_1 = (raw: RawClient["server.projectCopy"]) => (input: Endpoint20_1Input) =>
|
||||
raw["projectCopy.remove"]({
|
||||
params: { projectID: input["projectID"] },
|
||||
query: { location: input["location"] },
|
||||
payload: { directory: input["directory"], force: input["force"] },
|
||||
}).pipe(Effect.mapError(mapClientError))
|
||||
|
||||
type Endpoint19_2Request = Parameters<RawClient["server.projectCopy"]["projectCopy.refresh"]>[0]
|
||||
type Endpoint19_2Input = {
|
||||
readonly projectID: Endpoint19_2Request["params"]["projectID"]
|
||||
readonly location?: Endpoint19_2Request["query"]["location"]
|
||||
type Endpoint20_2Request = Parameters<RawClient["server.projectCopy"]["projectCopy.refresh"]>[0]
|
||||
type Endpoint20_2Input = {
|
||||
readonly projectID: Endpoint20_2Request["params"]["projectID"]
|
||||
readonly location?: Endpoint20_2Request["query"]["location"]
|
||||
}
|
||||
const Endpoint19_2 = (raw: RawClient["server.projectCopy"]) => (input: Endpoint19_2Input) =>
|
||||
const Endpoint20_2 = (raw: RawClient["server.projectCopy"]) => (input: Endpoint20_2Input) =>
|
||||
raw["projectCopy.refresh"]({
|
||||
params: { projectID: input["projectID"] },
|
||||
query: { location: input["location"] },
|
||||
}).pipe(Effect.mapError(mapClientError))
|
||||
|
||||
const adaptGroup19 = (raw: RawClient["server.projectCopy"]) => ({
|
||||
create: Endpoint19_0(raw),
|
||||
remove: Endpoint19_1(raw),
|
||||
refresh: Endpoint19_2(raw),
|
||||
const adaptGroup20 = (raw: RawClient["server.projectCopy"]) => ({
|
||||
create: Endpoint20_0(raw),
|
||||
remove: Endpoint20_1(raw),
|
||||
refresh: Endpoint20_2(raw),
|
||||
})
|
||||
|
||||
const adaptClient = (raw: RawClient) => ({
|
||||
|
|
@ -780,16 +801,17 @@ const adaptClient = (raw: RawClient) => ({
|
|||
providers: adaptGroup7(raw["server.provider"]),
|
||||
integrations: adaptGroup8(raw["server.integration"]),
|
||||
credentials: adaptGroup9(raw["server.credential"]),
|
||||
permissions: adaptGroup10(raw["server.permission"]),
|
||||
files: adaptGroup11(raw["server.fs"]),
|
||||
commands: adaptGroup12(raw["server.command"]),
|
||||
skills: adaptGroup13(raw["server.skill"]),
|
||||
events: adaptGroup14(raw["server.event"]),
|
||||
ptys: adaptGroup15(raw["server.pty"]),
|
||||
"server.shell": adaptGroup16(raw["server.shell"]),
|
||||
questions: adaptGroup17(raw["server.question"]),
|
||||
references: adaptGroup18(raw["server.reference"]),
|
||||
projectCopies: adaptGroup19(raw["server.projectCopy"]),
|
||||
project: adaptGroup10(raw["server.project"]),
|
||||
permissions: adaptGroup11(raw["server.permission"]),
|
||||
files: adaptGroup12(raw["server.fs"]),
|
||||
commands: adaptGroup13(raw["server.command"]),
|
||||
skills: adaptGroup14(raw["server.skill"]),
|
||||
events: adaptGroup15(raw["server.event"]),
|
||||
ptys: adaptGroup16(raw["server.pty"]),
|
||||
"server.shell": adaptGroup17(raw["server.shell"]),
|
||||
questions: adaptGroup18(raw["server.question"]),
|
||||
references: adaptGroup19(raw["server.reference"]),
|
||||
projectCopies: adaptGroup20(raw["server.projectCopy"]),
|
||||
})
|
||||
|
||||
export const make = (options?: { readonly baseUrl?: URL | string }) =>
|
||||
|
|
|
|||
|
|
@ -67,6 +67,10 @@ import type {
|
|||
CredentialsUpdateOutput,
|
||||
CredentialsRemoveInput,
|
||||
CredentialsRemoveOutput,
|
||||
ProjectCurrentInput,
|
||||
ProjectCurrentOutput,
|
||||
ProjectDirectoriesInput,
|
||||
ProjectDirectoriesOutput,
|
||||
PermissionsListRequestsInput,
|
||||
PermissionsListRequestsOutput,
|
||||
PermissionsListSavedInput,
|
||||
|
|
@ -704,6 +708,32 @@ export function make(options: ClientOptions) {
|
|||
requestOptions,
|
||||
),
|
||||
},
|
||||
project: {
|
||||
current: (input?: ProjectCurrentInput, requestOptions?: RequestOptions) =>
|
||||
request<ProjectCurrentOutput>(
|
||||
{
|
||||
method: "GET",
|
||||
path: `/api/project/current`,
|
||||
query: { location: input?.["location"] },
|
||||
successStatus: 200,
|
||||
declaredStatuses: [401, 400],
|
||||
empty: false,
|
||||
},
|
||||
requestOptions,
|
||||
),
|
||||
directories: (input: ProjectDirectoriesInput, requestOptions?: RequestOptions) =>
|
||||
request<ProjectDirectoriesOutput>(
|
||||
{
|
||||
method: "GET",
|
||||
path: `/api/project/${encodeURIComponent(input.projectID)}/directories`,
|
||||
query: { location: input["location"] },
|
||||
successStatus: 200,
|
||||
declaredStatuses: [401, 400],
|
||||
empty: false,
|
||||
},
|
||||
requestOptions,
|
||||
),
|
||||
},
|
||||
permissions: {
|
||||
listRequests: (input?: PermissionsListRequestsInput, requestOptions?: RequestOptions) =>
|
||||
request<PermissionsListRequestsOutput>(
|
||||
|
|
|
|||
|
|
@ -2339,6 +2339,23 @@ export type CredentialsRemoveInput = {
|
|||
|
||||
export type CredentialsRemoveOutput = void
|
||||
|
||||
export type ProjectCurrentInput = {
|
||||
readonly location?: {
|
||||
readonly location?: { readonly directory?: string | undefined; readonly workspace?: string | undefined } | undefined
|
||||
}["location"]
|
||||
}
|
||||
|
||||
export type ProjectCurrentOutput = { readonly id: string; readonly directory: string }
|
||||
|
||||
export type ProjectDirectoriesInput = {
|
||||
readonly projectID: { readonly projectID: string }["projectID"]
|
||||
readonly location?: {
|
||||
readonly location?: { readonly directory?: string | undefined; readonly workspace?: string | undefined } | undefined
|
||||
}["location"]
|
||||
}
|
||||
|
||||
export type ProjectDirectoriesOutput = ReadonlyArray<{ readonly directory: string; readonly strategy?: string }>
|
||||
|
||||
export type PermissionsListRequestsInput = {
|
||||
readonly location?: {
|
||||
readonly location?: { readonly directory?: string | undefined; readonly workspace?: string | undefined } | undefined
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ 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"
|
||||
|
|
@ -26,10 +27,14 @@ test("Core and Server reuse the authoritative Schema and Protocol values", () =>
|
|||
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.Admitted).toBe(SessionInput.Admitted)
|
||||
expect(CoreSessionMessage.Message).toBe(SessionMessage.Message)
|
||||
expect(CorePrompt).toBe(Prompt)
|
||||
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")
|
||||
|
|
|
|||
|
|
@ -15,12 +15,14 @@ test("exposes every standard HTTP API group", () => {
|
|||
"providers",
|
||||
"integrations",
|
||||
"credentials",
|
||||
"project",
|
||||
"permissions",
|
||||
"files",
|
||||
"commands",
|
||||
"skills",
|
||||
"events",
|
||||
"ptys",
|
||||
"server.shell",
|
||||
"questions",
|
||||
"references",
|
||||
"projectCopies",
|
||||
|
|
@ -37,6 +39,33 @@ test("exposes every standard HTTP API group", () => {
|
|||
])
|
||||
expect(Object.keys(client.files)).toEqual(["list", "find"])
|
||||
expect(Object.keys(client.ptys)).toEqual(["list", "create", "get", "update", "remove"])
|
||||
expect(Object.keys(client.project)).toEqual(["current", "directories"])
|
||||
})
|
||||
|
||||
test("project methods use the public HTTP contract", async () => {
|
||||
const requests: string[] = []
|
||||
const client = OpenCode.make({
|
||||
baseUrl: "http://localhost:3000",
|
||||
fetch: async (input) => {
|
||||
const url = typeof input === "string" ? input : input instanceof URL ? input.href : input.url
|
||||
requests.push(url)
|
||||
if (url.includes("/directories")) return Response.json([])
|
||||
return Response.json({ id: "proj_test", directory: "/tmp/project" })
|
||||
},
|
||||
})
|
||||
|
||||
const current = await client.project.current({ location: { workspace: "wrk_test" } })
|
||||
const directories = await client.project.directories({
|
||||
projectID: current.id,
|
||||
location: { directory: current.directory },
|
||||
})
|
||||
|
||||
expect(current).toEqual({ id: "proj_test", directory: "/tmp/project" })
|
||||
expect(directories).toEqual([])
|
||||
expect(requests).toEqual([
|
||||
"http://localhost:3000/api/project/current?location%5Bworkspace%5D=wrk_test",
|
||||
"http://localhost:3000/api/project/proj_test/directories?location%5Bdirectory%5D=%2Ftmp%2Fproject",
|
||||
])
|
||||
})
|
||||
|
||||
test("sessions.get returns the wire projection", async () => {
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import { PermissionV2 } from "./permission"
|
|||
import { PluginV2 } from "./plugin"
|
||||
import { PluginInternal } from "./plugin/internal"
|
||||
import { Policy } from "./policy"
|
||||
import { Project } from "./project"
|
||||
import { ProjectCopy } from "./project/copy"
|
||||
import { Pty } from "./pty"
|
||||
import { QuestionV2 } from "./question"
|
||||
|
|
@ -43,6 +44,7 @@ import { ToolOutputStore } from "./tool-output-store"
|
|||
export { LocationServiceMap } from "./location-service-map"
|
||||
|
||||
export const locationServices = LayerNode.group([
|
||||
Project.node,
|
||||
Location.node,
|
||||
Policy.node,
|
||||
Config.node,
|
||||
|
|
|
|||
|
|
@ -17,14 +17,20 @@ export type ID = ProjectSchema.ID
|
|||
export const Vcs = ProjectSchema.Vcs
|
||||
export type Vcs = ProjectSchema.Vcs
|
||||
|
||||
export const Current = ProjectSchema.Current
|
||||
export type Current = ProjectSchema.Current
|
||||
|
||||
export const Directory = ProjectSchema.Directory
|
||||
export type Directory = ProjectSchema.Directory
|
||||
|
||||
export class Info extends Schema.Class<Info>("Project.Info")({
|
||||
id: ID,
|
||||
}) {}
|
||||
|
||||
export const DirectoriesInput = ProjectDirectories.ListInput
|
||||
export const DirectoriesInput = ProjectSchema.DirectoriesInput
|
||||
export type DirectoriesInput = typeof DirectoriesInput.Type
|
||||
|
||||
export const Directories = ProjectDirectories.ListOutput
|
||||
export const Directories = ProjectSchema.Directories
|
||||
export type Directories = typeof Directories.Type
|
||||
|
||||
export interface Resolved {
|
||||
|
|
|
|||
|
|
@ -4,15 +4,13 @@ import { and, asc, desc, eq, isNotNull, isNull, ne, or } from "drizzle-orm"
|
|||
import { Context, Effect, Layer, Schema } from "effect"
|
||||
import { Database } from "../database/database"
|
||||
import { makeGlobalNode } from "../effect/app-node"
|
||||
import { AbsolutePath, optional } from "../schema"
|
||||
import { AbsolutePath } from "../schema"
|
||||
import { ProjectSchema } from "./schema"
|
||||
import { ProjectDirectoryTable } from "./sql"
|
||||
import type { EffectDrizzleSqlite } from "@opencode-ai/effect-drizzle-sqlite"
|
||||
import type { Project } from "../project"
|
||||
|
||||
export interface Directory {
|
||||
readonly directory: AbsolutePath
|
||||
readonly strategy?: string
|
||||
}
|
||||
export type Directory = Project.Directory
|
||||
|
||||
export const CreateInput = Schema.Struct({
|
||||
projectID: ProjectSchema.ID,
|
||||
|
|
@ -31,17 +29,10 @@ export type RemoveInput = typeof RemoveInput.Type
|
|||
type DatabaseClient = EffectDrizzleSqlite.EffectSQLiteDatabase
|
||||
export type Transaction = Parameters<Parameters<DatabaseClient["transaction"]>[0]>[0]
|
||||
|
||||
export const ListInput = Schema.Struct({
|
||||
projectID: ProjectSchema.ID,
|
||||
}).annotate({ identifier: "Project.DirectoriesInput" })
|
||||
export const ListInput = ProjectSchema.DirectoriesInput
|
||||
export type ListInput = typeof ListInput.Type
|
||||
|
||||
export const ListOutput = Schema.Array(
|
||||
Schema.Struct({
|
||||
directory: AbsolutePath,
|
||||
strategy: optional(Schema.String),
|
||||
}),
|
||||
).annotate({ identifier: "Project.Directories" })
|
||||
export const ListOutput = ProjectSchema.Directories
|
||||
export type ListOutput = typeof ListOutput.Type
|
||||
|
||||
export interface Interface {
|
||||
|
|
|
|||
|
|
@ -7,6 +7,18 @@ import { AbsolutePath } from "../schema"
|
|||
export const ID = Project.ID
|
||||
export type ID = typeof ID.Type
|
||||
|
||||
export const Current = Project.Current
|
||||
export type Current = typeof Current.Type
|
||||
|
||||
export const Directory = Project.Directory
|
||||
export type Directory = typeof Directory.Type
|
||||
|
||||
export const DirectoriesInput = Project.DirectoriesInput
|
||||
export type DirectoriesInput = typeof DirectoriesInput.Type
|
||||
|
||||
export const Directories = Project.Directories
|
||||
export type Directories = typeof Directories.Type
|
||||
|
||||
export const Vcs = Schema.Union([
|
||||
Schema.Struct({
|
||||
type: Schema.Literal("git"),
|
||||
|
|
|
|||
|
|
@ -121,12 +121,12 @@ describe("LocationServiceMap", () => {
|
|||
expect(blockedState.tools.map((tool) => tool.name).sort()).toEqual([
|
||||
"application_context",
|
||||
"apply_patch",
|
||||
"bash",
|
||||
"edit",
|
||||
"glob",
|
||||
"grep",
|
||||
"question",
|
||||
"read",
|
||||
"shell",
|
||||
"skill",
|
||||
"todowrite",
|
||||
"webfetch",
|
||||
|
|
@ -138,12 +138,12 @@ describe("LocationServiceMap", () => {
|
|||
expect(allowedState.tools.map((tool) => tool.name).sort()).toEqual([
|
||||
"application_context",
|
||||
"apply_patch",
|
||||
"bash",
|
||||
"edit",
|
||||
"glob",
|
||||
"grep",
|
||||
"question",
|
||||
"read",
|
||||
"shell",
|
||||
"skill",
|
||||
"todowrite",
|
||||
"webfetch",
|
||||
|
|
|
|||
|
|
@ -44,6 +44,14 @@ describe("ProjectDirectories", () => {
|
|||
}),
|
||||
)
|
||||
|
||||
it.effect("returns an empty list for missing projects", () =>
|
||||
Effect.gen(function* () {
|
||||
const service = yield* ProjectDirectories.Service
|
||||
|
||||
expect(yield* service.list(Project.ID.make("missing-project"))).toEqual([])
|
||||
}),
|
||||
)
|
||||
|
||||
it.effect("replaces the strategy when requested", () =>
|
||||
Effect.gen(function* () {
|
||||
yield* setup()
|
||||
|
|
|
|||
|
|
@ -134,6 +134,10 @@ test("Core reuses the canonical shared schemas", async () => {
|
|||
[corePty.Info, Pty.Info],
|
||||
[corePty.Event, Pty.Event],
|
||||
[coreProject.ID, Project.ID],
|
||||
[coreProject.Current, Project.Current],
|
||||
[coreProject.Directory, Project.Directory],
|
||||
[coreProject.DirectoriesInput, Project.DirectoriesInput],
|
||||
[coreProject.Directories, Project.Directories],
|
||||
[coreReference.LocalSource, Reference.LocalSource],
|
||||
[coreReference.GitSource, Reference.GitSource],
|
||||
[coreReference.Source, Reference.Source],
|
||||
|
|
|
|||
|
|
@ -88,6 +88,18 @@ const call = (input: typeof ShellTool.Input.Type, id = "call-shell") => ({
|
|||
call: { type: "tool-call" as const, id, name: "shell", input },
|
||||
})
|
||||
|
||||
const isWindows = process.platform === "win32"
|
||||
const cwdCommand = isWindows ? "(Get-Location).Path; Start-Sleep -Milliseconds 100" : "pwd"
|
||||
const helloCommand = isWindows ? "[Console]::Out.Write('hello'); Start-Sleep -Milliseconds 100" : "printf hello"
|
||||
const idleCommand = isWindows ? "Start-Sleep -Seconds 60" : "sleep 60"
|
||||
const bodyExitCommand = isWindows
|
||||
? "[Console]::Out.Write('body'); Start-Sleep -Milliseconds 100; exit 7"
|
||||
: "printf body && exit 7"
|
||||
const overflowCommand = (bytes: number) =>
|
||||
isWindows
|
||||
? `[Console]::Out.Write(('x' * ${bytes})); Start-Sleep -Milliseconds 100`
|
||||
: `head -c ${bytes} /dev/zero | tr '\\0' 'x'`
|
||||
|
||||
const it = testEffect(Layer.empty)
|
||||
|
||||
describe("ShellTool", () => {
|
||||
|
|
@ -103,14 +115,14 @@ describe("ShellTool", () => {
|
|||
expect(definitions[0]?.outputSchema).not.toHaveProperty("properties.output")
|
||||
expect(yield* toolDefinitions(registry, [{ action: "shell", resource: "*", effect: "deny" }])).toEqual([])
|
||||
|
||||
const settled = yield* settleTool(registry, call({ command: "printf hello" }))
|
||||
const settled = yield* settleTool(registry, call({ command: helloCommand }))
|
||||
expect(settled.output?.structured).toMatchObject({ exit: 0, truncated: false })
|
||||
expect(settled.output?.content[0]).toEqual({ type: "text", text: "hello" })
|
||||
expect(settled.output?.content[1]).toMatchObject({
|
||||
type: "text",
|
||||
text: expect.stringContaining("Command exited with code 0."),
|
||||
})
|
||||
expect(assertions).toMatchObject([{ sessionID, action: "shell", resources: ["printf hello"] }])
|
||||
expect(assertions).toMatchObject([{ sessionID, action: "shell", resources: [helloCommand] }])
|
||||
}),
|
||||
)
|
||||
},
|
||||
|
|
@ -128,7 +140,9 @@ describe("ShellTool", () => {
|
|||
reset()
|
||||
return Effect.promise(() => fs.mkdir(path.join(tmp.path, "src"))).pipe(
|
||||
Effect.andThen(
|
||||
withTool(data.path, tmp.path, (registry) => settleTool(registry, call({ command: "pwd", workdir: "src" }))),
|
||||
withTool(data.path, tmp.path, (registry) =>
|
||||
settleTool(registry, call({ command: cwdCommand, workdir: "src" })),
|
||||
),
|
||||
),
|
||||
Effect.andThen((settled) =>
|
||||
Effect.sync(() =>
|
||||
|
|
@ -163,7 +177,7 @@ describe("ShellTool", () => {
|
|||
return Effect.promise(() => fs.mkdir(workdir)).pipe(
|
||||
Effect.andThen(
|
||||
withTool(data.path, tmp.path, (registry) =>
|
||||
executeTool(registry, call({ command: "pwd", workdir: "src" })),
|
||||
executeTool(registry, call({ command: cwdCommand, workdir: "src" })),
|
||||
),
|
||||
),
|
||||
Effect.andThen(Effect.sync(() => expect(assertions.map((input) => input.action)).toEqual(["shell"]))),
|
||||
|
|
@ -182,7 +196,7 @@ describe("ShellTool", () => {
|
|||
([data, active, outside]) => {
|
||||
reset()
|
||||
return withTool(data.path, active.path, (registry) =>
|
||||
executeTool(registry, call({ command: "pwd", workdir: outside.path })),
|
||||
executeTool(registry, call({ command: cwdCommand, workdir: outside.path })),
|
||||
).pipe(
|
||||
Effect.andThen(
|
||||
Effect.sync(() => {
|
||||
|
|
@ -213,13 +227,13 @@ describe("ShellTool", () => {
|
|||
reset()
|
||||
denyAction = "external_directory"
|
||||
yield* withTool(data.path, active.path, (registry) =>
|
||||
executeTool(registry, call({ command: "pwd", workdir: outside.path })),
|
||||
executeTool(registry, call({ command: cwdCommand, workdir: outside.path })),
|
||||
)
|
||||
expect(assertions.map((item) => item.action)).toEqual(["external_directory"])
|
||||
|
||||
reset()
|
||||
denyAction = "shell"
|
||||
yield* withTool(data.path, active.path, (registry) => executeTool(registry, call({ command: "pwd" })))
|
||||
yield* withTool(data.path, active.path, (registry) => executeTool(registry, call({ command: cwdCommand })))
|
||||
expect(assertions.map((item) => item.action)).toEqual(["shell"])
|
||||
}),
|
||||
([data, active, outside]) =>
|
||||
|
|
@ -272,7 +286,7 @@ describe("ShellTool", () => {
|
|||
([data, tmp]) => {
|
||||
reset()
|
||||
return withTool(data.path, tmp.path, (registry) =>
|
||||
settleTool(registry, call({ command: "printf body && exit 7" }, "call-nonzero")),
|
||||
settleTool(registry, call({ command: bodyExitCommand }, "call-nonzero")),
|
||||
).pipe(
|
||||
Effect.andThen((settled) =>
|
||||
Effect.sync(() => {
|
||||
|
|
@ -300,7 +314,7 @@ describe("ShellTool", () => {
|
|||
reset()
|
||||
const bytes = ShellTool.MAX_CAPTURE_BYTES + 1024
|
||||
return withTool(data.path, tmp.path, (registry) =>
|
||||
settleTool(registry, call({ command: `head -c ${bytes} /dev/zero | tr '\\0' 'x'` }, "call-overflow")),
|
||||
settleTool(registry, call({ command: overflowCommand(bytes) }, "call-overflow")),
|
||||
).pipe(
|
||||
Effect.andThen((settled) =>
|
||||
Effect.sync(() => {
|
||||
|
|
@ -326,7 +340,7 @@ describe("ShellTool", () => {
|
|||
([data, tmp]) => {
|
||||
reset()
|
||||
return withTool(data.path, tmp.path, (registry) =>
|
||||
settleTool(registry, call({ command: "sleep 60", timeout: 50 })),
|
||||
settleTool(registry, call({ command: idleCommand, timeout: 50 })),
|
||||
).pipe(
|
||||
Effect.andThen((settled) =>
|
||||
Effect.sync(() => {
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import { Authorization } from "./middleware/authorization"
|
|||
import { LocationGroup } from "./groups/location"
|
||||
import { IntegrationGroup } from "./groups/integration"
|
||||
import { CredentialGroup } from "./groups/credential"
|
||||
import { ProjectGroup } from "./groups/project"
|
||||
import { ProjectCopyGroup } from "./groups/project-copy"
|
||||
|
||||
// Protocol owns middleware placement, while Server injects concrete keys so Core service identities stay downstream.
|
||||
|
|
@ -47,6 +48,7 @@ const makeApiFromGroup = <
|
|||
.add(ProviderGroup.middleware(locationMiddleware))
|
||||
.add(IntegrationGroup.middleware(locationMiddleware))
|
||||
.add(CredentialGroup.middleware(locationMiddleware))
|
||||
.add(ProjectGroup.middleware(locationMiddleware))
|
||||
.add(makePermissionGroup(locationMiddleware, sessionLocationMiddleware))
|
||||
.add(FileSystemGroup.middleware(locationMiddleware))
|
||||
.add(CommandGroup.middleware(locationMiddleware))
|
||||
|
|
|
|||
42
packages/protocol/src/groups/project.ts
Normal file
42
packages/protocol/src/groups/project.ts
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
import { Project } from "@opencode-ai/schema/project"
|
||||
import { HttpApiEndpoint, HttpApiGroup, OpenApi } from "effect/unstable/httpapi"
|
||||
import { LocationQuery, locationQueryOpenApi } from "./location"
|
||||
|
||||
const root = "/api/project"
|
||||
|
||||
export const ProjectGroup = HttpApiGroup.make("server.project")
|
||||
.add(
|
||||
HttpApiEndpoint.get("project.current", `${root}/current`, {
|
||||
query: LocationQuery,
|
||||
success: Project.Current,
|
||||
})
|
||||
.annotateMerge(locationQueryOpenApi)
|
||||
.annotateMerge(
|
||||
OpenApi.annotations({
|
||||
identifier: "v2.project.current",
|
||||
summary: "Get current project",
|
||||
description: "Resolve the project for the requested location.",
|
||||
}),
|
||||
),
|
||||
)
|
||||
.add(
|
||||
HttpApiEndpoint.get("project.directories", `${root}/:projectID/directories`, {
|
||||
params: { projectID: Project.ID },
|
||||
query: LocationQuery,
|
||||
success: Project.Directories,
|
||||
})
|
||||
.annotateMerge(locationQueryOpenApi)
|
||||
.annotateMerge(
|
||||
OpenApi.annotations({
|
||||
identifier: "v2.project.directories",
|
||||
summary: "List project directories",
|
||||
description: "List known local absolute directories for a project.",
|
||||
}),
|
||||
),
|
||||
)
|
||||
.annotateMerge(
|
||||
OpenApi.annotations({
|
||||
title: "projects",
|
||||
description: "Location-scoped project routes.",
|
||||
}),
|
||||
)
|
||||
|
|
@ -2,13 +2,29 @@ export * as Project from "./project"
|
|||
|
||||
import { Schema } from "effect"
|
||||
import { define, inventory } from "./event"
|
||||
import { NonNegativeInt, optional } from "./schema"
|
||||
import { AbsolutePath, NonNegativeInt, optional } from "./schema"
|
||||
import { ProjectID } from "./project-id"
|
||||
|
||||
export const ID = ProjectID
|
||||
export type ID = typeof ID.Type
|
||||
|
||||
export const Vcs = Schema.Literal("git").annotate({ identifier: "Project.Vcs" })
|
||||
export const Current = Schema.Struct({
|
||||
id: ID,
|
||||
directory: AbsolutePath,
|
||||
}).annotate({ identifier: "Project.Current" })
|
||||
export interface Current extends Schema.Schema.Type<typeof Current> {}
|
||||
export const Directory = Schema.Struct({
|
||||
directory: AbsolutePath,
|
||||
strategy: optional(Schema.String),
|
||||
}).annotate({ identifier: "Project.Directory" })
|
||||
export interface Directory extends Schema.Schema.Type<typeof Directory> {}
|
||||
export const DirectoriesInput = Schema.Struct({
|
||||
projectID: ID,
|
||||
}).annotate({ identifier: "Project.DirectoriesInput" })
|
||||
export interface DirectoriesInput extends Schema.Schema.Type<typeof DirectoriesInput> {}
|
||||
export const Directories = Schema.Array(Directory).annotate({ identifier: "Project.Directories" })
|
||||
export type Directories = typeof Directories.Type
|
||||
export const Icon = Schema.Struct({
|
||||
url: optional(Schema.String),
|
||||
override: optional(Schema.String),
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ import { Project } from "../src/project"
|
|||
import { Pty } from "../src/pty"
|
||||
import { Question } from "../src/question"
|
||||
import { Session } from "../src/session"
|
||||
import { SessionEvent } from "../src/session-event"
|
||||
import { SessionTodo } from "../src/session-todo"
|
||||
import { optional } from "../src/schema"
|
||||
|
||||
|
|
@ -41,6 +40,10 @@ describe("contract hygiene", () => {
|
|||
Model.Capabilities,
|
||||
Model.Cost,
|
||||
Model.Api,
|
||||
Project.Current,
|
||||
Project.Directory,
|
||||
Project.DirectoriesInput,
|
||||
Project.Directories,
|
||||
Project.Icon,
|
||||
Project.Commands,
|
||||
Project.Time,
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import { ReferenceHandler } from "./handlers/reference"
|
|||
import { LocationHandler } from "./handlers/location"
|
||||
import { IntegrationHandler } from "./handlers/integration"
|
||||
import { CredentialHandler } from "./handlers/credential"
|
||||
import { ProjectHandler } from "./handlers/project"
|
||||
import { ProjectCopyHandler } from "./handlers/project-copy"
|
||||
|
||||
export const handlers = Layer.mergeAll(
|
||||
|
|
@ -31,6 +32,7 @@ export const handlers = Layer.mergeAll(
|
|||
ProviderHandler,
|
||||
IntegrationHandler,
|
||||
CredentialHandler,
|
||||
ProjectHandler,
|
||||
PermissionHandler,
|
||||
FileSystemHandler,
|
||||
CommandHandler,
|
||||
|
|
|
|||
17
packages/server/src/handlers/project.ts
Normal file
17
packages/server/src/handlers/project.ts
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
import { Location } from "@opencode-ai/core/location"
|
||||
import { Project } from "@opencode-ai/core/project"
|
||||
import { Effect } from "effect"
|
||||
import { HttpApiBuilder } from "effect/unstable/httpapi"
|
||||
import { Api } from "../api"
|
||||
|
||||
export const ProjectHandler = HttpApiBuilder.group(Api, "server.project", (handlers) =>
|
||||
handlers
|
||||
.handle("project.current", () =>
|
||||
Location.Service.use((location) =>
|
||||
Effect.succeed({ id: location.project.id, directory: location.project.directory }),
|
||||
),
|
||||
)
|
||||
.handle("project.directories", (ctx) =>
|
||||
Project.Service.use((project) => project.directories({ projectID: ctx.params.projectID })),
|
||||
),
|
||||
)
|
||||
|
|
@ -17,18 +17,18 @@ import { useCommandShortcut } from "../keymap"
|
|||
import { useProject } from "../context/project"
|
||||
import { Spinner } from "./spinner"
|
||||
import { DialogWorkspaceFileChanges } from "./dialog-workspace-file-changes"
|
||||
import type { ProjectDirectories } from "@opencode-ai/sdk/v2"
|
||||
import type { ProjectDirectoriesOutput } from "@opencode-ai/client"
|
||||
import { useRoute } from "../context/route"
|
||||
|
||||
export type MoveSessionSelection = { type: "directory"; directory: string; subdirectory: boolean } | { type: "new" }
|
||||
type ProjectDirectory = ProjectDirectories[number]
|
||||
type ProjectDirectory = ProjectDirectoriesOutput[number]
|
||||
|
||||
type DialogMoveSessionProps = {
|
||||
projectID: string
|
||||
current?: MoveSessionSelection
|
||||
onSelect: (selection: MoveSessionSelection) => void
|
||||
onCurrentChange?: (selection: MoveSessionSelection) => void
|
||||
initialDirectories?: ProjectDirectory[]
|
||||
initialDirectories?: ReadonlyArray<ProjectDirectory>
|
||||
initialRemoving?: string
|
||||
}
|
||||
|
||||
|
|
@ -58,12 +58,13 @@ export function DialogMoveSession(props: DialogMoveSessionProps) {
|
|||
|
||||
// A failed current-checkout lookup only affects which row is highlighted, so
|
||||
// swallow it and let the directory list render without a current marker.
|
||||
// Once the current project is known, a mismatch is a guaranteed miss.
|
||||
const [loadedProject] = createResource(
|
||||
() => (projectContext.project() === props.projectID ? undefined : props.projectID),
|
||||
() => (projectContext.project() === undefined ? props.projectID : undefined),
|
||||
(projectID) =>
|
||||
sdk.client.project
|
||||
.current({}, { throwOnError: true })
|
||||
.then((result) => (result.data?.id === projectID ? result.data.worktree : undefined))
|
||||
sdk.api.project
|
||||
.current({ location: { directory: projectContext.instance.directory() || paths.cwd } })
|
||||
.then((project) => (project.id === projectID ? project.directory : undefined))
|
||||
.catch(() => undefined),
|
||||
)
|
||||
const currentCheckout = createMemo(() => {
|
||||
|
|
@ -73,15 +74,19 @@ export function DialogMoveSession(props: DialogMoveSessionProps) {
|
|||
|
||||
const [directories, { refetch }] = createResource(
|
||||
() => (props.initialRemoving ? undefined : props.projectID),
|
||||
async (projectID, info): Promise<ProjectDirectory[] | undefined> => {
|
||||
async (projectID, info): Promise<ReadonlyArray<ProjectDirectory> | undefined> => {
|
||||
try {
|
||||
const location = { directory: projectContext.instance.directory() || paths.cwd }
|
||||
await sdk.api.projectCopies.refresh({
|
||||
projectID,
|
||||
location: { directory: projectContext.instance.directory() || paths.cwd },
|
||||
location,
|
||||
})
|
||||
const directories = await sdk.api.project.directories({
|
||||
projectID,
|
||||
location,
|
||||
})
|
||||
const directories = await sdk.client.project.directories({ projectID }, { throwOnError: true })
|
||||
setLoadError(undefined)
|
||||
return directories.data ?? []
|
||||
return directories
|
||||
} catch (error) {
|
||||
setLoadError(error)
|
||||
// An initial load with no data surfaces the inline error view below. A
|
||||
|
|
|
|||
|
|
@ -37,18 +37,17 @@ export const { use: useProject, provider: ProjectProvider } = createSimpleContex
|
|||
|
||||
async function sync() {
|
||||
const workspace = store.workspace.current
|
||||
const location = { workspace }
|
||||
const [instancePath, project] = await Promise.all([
|
||||
sdk.client.path.get({ workspace }),
|
||||
sdk.client.project.current({ workspace }),
|
||||
sdk.api.project.current({ location }),
|
||||
])
|
||||
const directories = project.data?.id
|
||||
? await sdk.client.project.directories({ projectID: project.data.id, workspace })
|
||||
: undefined
|
||||
const directories = await sdk.api.project.directories({ projectID: project.id, location })
|
||||
batch(() => {
|
||||
setStore("instance", "path", reconcile(instancePath.data || defaultPath))
|
||||
setStore("project", "id", project.data?.id)
|
||||
setStore("project", "worktree", project.data?.worktree)
|
||||
setStore("project", "mainDir", directories?.data?.findLast((item) => item.strategy === undefined)?.directory)
|
||||
setStore("project", "id", project.id)
|
||||
setStore("project", "worktree", project.directory)
|
||||
setStore("project", "mainDir", directories.findLast((item) => item.strategy === undefined)?.directory)
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -93,6 +93,9 @@ export function createFetch(override?: FetchHandler, events?: ReturnType<typeof
|
|||
if (url.pathname === "/experimental/capabilities") return json({ backgroundSubagents: false })
|
||||
if (url.pathname === "/path") return json({ home: "", state: "", config: "", worktree, directory })
|
||||
if (url.pathname === "/api/location") return json({ directory, project: { id: "proj_test", directory: worktree } })
|
||||
if (url.pathname === "/api/project/current") return json({ id: "proj_test", directory: worktree })
|
||||
if (url.pathname === "/api/project/proj_test/directories") return json([{ directory: worktree }])
|
||||
if (url.pathname === "/api/shell") return json({ data: [] })
|
||||
if (url.pathname === "/api/session") return json({ data: [], cursor: {} })
|
||||
if (url.pathname === "/api/session/active") return json({ data: {} })
|
||||
if (
|
||||
|
|
@ -104,7 +107,6 @@ export function createFetch(override?: FetchHandler, events?: ReturnType<typeof
|
|||
location: { directory, project: { id: "proj_test", directory: worktree } },
|
||||
data: [],
|
||||
})
|
||||
if (url.pathname === "/project/current") return json({ id: "proj_test" })
|
||||
if (url.pathname === "/api/reference")
|
||||
return json({ location: { directory, project: { id: "proj_test", directory } }, data: [] })
|
||||
if (url.pathname === "/provider") return json({ all: [], default: {}, connected: [] })
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue