diff --git a/packages/client/README.md b/packages/client/README.md index fc167950751b..8c53e47c7e68 100644 --- a/packages/client/README.md +++ b/packages/client/README.md @@ -7,7 +7,7 @@ Private generation target for clients derived directly from OpenCode's authorita - `@opencode-ai/client`: zero-Effect Promise client using `fetch`. - `@opencode-ai/client/effect`: rich Effect network client using an environment-provided `HttpClient`. -The generated surface starts with the Session group from Server's concrete API. The build compiler reads `@opencode-ai/server/api`; the generated Effect runtime imports a client-local projection built from Protocol, with a generation-equivalence test preventing transport drift. Run `bun run generate` after changing the contract and `bun run check:generated` to detect committed-output drift. +The generated surface includes every standard HTTP group from Server's concrete API. The build compiler reads `@opencode-ai/server/api`; the generated Effect runtime imports a client-local projection built from Protocol, with a generation-equivalence test preventing transport drift. Custom transports such as the PTY WebSocket connection remain outside the generic HTTP client. Run `bun run generate` after changing the contract and `bun run check:generated` to detect committed-output drift. The Effect entrypoint uses canonical decoded values such as `Session.ID`, `Location.Ref`, and `Prompt`. These datatypes come from the lightweight `@opencode-ai/schema` package and are re-exported so callers depend only on the client surface. Protocol owns endpoint construction and middleware placement; Server supplies the concrete middleware keys used by the build-time API. diff --git a/packages/client/script/build.ts b/packages/client/script/build.ts index 88e5ea6e5bcc..aeec4b3e3451 100644 --- a/packages/client/script/build.ts +++ b/packages/client/script/build.ts @@ -1,12 +1,10 @@ import { NodeFileSystem } from "@effect/platform-node" import { compile, emitEffectImported, emitPromise, write } from "@opencode-ai/httpapi-codegen" -import { ClientApi } from "../src/contract" +import { ClientApi, endpointNames, groupNames, omitEndpoints } from "../src/contract" import { Effect } from "effect" import { fileURLToPath } from "url" -const contract = compile(ClientApi, { - groupNames: { "server.session": "sessions", "server.event": "events" }, -}) +const contract = compile(ClientApi, { groupNames, endpointNames, omitEndpoints }) await Effect.runPromise( Effect.all( diff --git a/packages/client/src/contract.ts b/packages/client/src/contract.ts index 15769ad9c2a0..413fea9dc338 100644 --- a/packages/client/src/contract.ts +++ b/packages/client/src/contract.ts @@ -1,6 +1,6 @@ import { makeDefaultApi } from "@opencode-ai/protocol/api" import { InvalidRequestError, SessionNotFoundError } from "@opencode-ai/protocol/errors" -import { HttpApi, HttpApiMiddleware } from "effect/unstable/httpapi" +import { HttpApiMiddleware } from "effect/unstable/httpapi" class LocationMiddleware extends HttpApiMiddleware.Service()( "@opencode-ai/client/LocationMiddleware", @@ -11,11 +11,43 @@ class SessionLocationMiddleware extends HttpApiMiddleware.Service(error: E) => ? new ClientError({ cause: error }) : error -type Endpoint0_0Request = Parameters[0] -type Endpoint0_0Input = { - readonly workspace?: Endpoint0_0Request["query"]["workspace"] - readonly limit?: Endpoint0_0Request["query"]["limit"] - readonly order?: Endpoint0_0Request["query"]["order"] - readonly search?: Endpoint0_0Request["query"]["search"] - readonly directory?: Endpoint0_0Request["query"]["directory"] - readonly project?: Endpoint0_0Request["query"]["project"] - readonly subpath?: Endpoint0_0Request["query"]["subpath"] - readonly cursor?: Endpoint0_0Request["query"]["cursor"] -} -const Endpoint0_0 = (raw: RawClient["server.session"]) => (input?: Endpoint0_0Input) => +const Endpoint0_0 = (raw: RawClient["server.health"]) => () => + raw["health.get"]({}).pipe(Effect.mapError(mapClientError)) + +const adaptGroup0 = (raw: RawClient["server.health"]) => ({ get: Endpoint0_0(raw) }) + +type Endpoint1_0Request = Parameters[0] +type Endpoint1_0Input = { readonly location?: Endpoint1_0Request["query"]["location"] } +const Endpoint1_0 = (raw: RawClient["server.location"]) => (input?: Endpoint1_0Input) => + raw["location.get"]({ query: { location: input?.["location"] } }).pipe(Effect.mapError(mapClientError)) + +const adaptGroup1 = (raw: RawClient["server.location"]) => ({ get: Endpoint1_0(raw) }) + +type Endpoint2_0Request = Parameters[0] +type Endpoint2_0Input = { readonly location?: Endpoint2_0Request["query"]["location"] } +const Endpoint2_0 = (raw: RawClient["server.agent"]) => (input?: Endpoint2_0Input) => + raw["agent.list"]({ query: { location: input?.["location"] } }).pipe(Effect.mapError(mapClientError)) + +const adaptGroup2 = (raw: RawClient["server.agent"]) => ({ list: Endpoint2_0(raw) }) + +type Endpoint3_0Request = Parameters[0] +type Endpoint3_0Input = { + readonly workspace?: Endpoint3_0Request["query"]["workspace"] + readonly limit?: Endpoint3_0Request["query"]["limit"] + readonly order?: Endpoint3_0Request["query"]["order"] + readonly search?: Endpoint3_0Request["query"]["search"] + readonly directory?: Endpoint3_0Request["query"]["directory"] + readonly project?: Endpoint3_0Request["query"]["project"] + readonly subpath?: Endpoint3_0Request["query"]["subpath"] + readonly cursor?: Endpoint3_0Request["query"]["cursor"] +} +const Endpoint3_0 = (raw: RawClient["server.session"]) => (input?: Endpoint3_0Input) => raw["session.list"]({ query: { - workspace: input?.workspace, - limit: input?.limit, - order: input?.order, - search: input?.search, - directory: input?.directory, - project: input?.project, - subpath: input?.subpath, - cursor: input?.cursor, + workspace: input?.["workspace"], + limit: input?.["limit"], + order: input?.["order"], + search: input?.["search"], + directory: input?.["directory"], + project: input?.["project"], + subpath: input?.["subpath"], + cursor: input?.["cursor"], }, }).pipe(Effect.mapError(mapClientError)) -type Endpoint0_1Request = Parameters[0] -type Endpoint0_1Input = { - readonly id?: Endpoint0_1Request["payload"]["id"] - readonly agent?: Endpoint0_1Request["payload"]["agent"] - readonly model?: Endpoint0_1Request["payload"]["model"] - readonly location?: Endpoint0_1Request["payload"]["location"] +type Endpoint3_1Request = Parameters[0] +type Endpoint3_1Input = { + readonly id?: Endpoint3_1Request["payload"]["id"] + readonly agent?: Endpoint3_1Request["payload"]["agent"] + readonly model?: Endpoint3_1Request["payload"]["model"] + readonly location?: Endpoint3_1Request["payload"]["location"] } -const Endpoint0_1 = (raw: RawClient["server.session"]) => (input?: Endpoint0_1Input) => +const Endpoint3_1 = (raw: RawClient["server.session"]) => (input?: Endpoint3_1Input) => raw["session.create"]({ - payload: { id: input?.id, agent: input?.agent, model: input?.model, location: input?.location }, + payload: { id: input?.["id"], agent: input?.["agent"], model: input?.["model"], location: input?.["location"] }, }).pipe( Effect.mapError(mapClientError), Effect.map((value) => value.data), ) -const Endpoint0_2 = (raw: RawClient["server.session"]) => () => +const Endpoint3_2 = (raw: RawClient["server.session"]) => () => raw["session.active"]({}).pipe( Effect.mapError(mapClientError), Effect.map((value) => value.data), ) -type Endpoint0_3Request = Parameters[0] -type Endpoint0_3Input = { readonly sessionID: Endpoint0_3Request["params"]["sessionID"] } -const Endpoint0_3 = (raw: RawClient["server.session"]) => (input: Endpoint0_3Input) => - raw["session.get"]({ params: { sessionID: input.sessionID } }).pipe( +type Endpoint3_3Request = Parameters[0] +type Endpoint3_3Input = { readonly sessionID: Endpoint3_3Request["params"]["sessionID"] } +const Endpoint3_3 = (raw: RawClient["server.session"]) => (input: Endpoint3_3Input) => + raw["session.get"]({ params: { sessionID: input["sessionID"] } }).pipe( Effect.mapError(mapClientError), Effect.map((value) => value.data), ) -type Endpoint0_4Request = Parameters[0] -type Endpoint0_4Input = { - readonly sessionID: Endpoint0_4Request["params"]["sessionID"] - readonly agent: Endpoint0_4Request["payload"]["agent"] +type Endpoint3_4Request = Parameters[0] +type Endpoint3_4Input = { + readonly sessionID: Endpoint3_4Request["params"]["sessionID"] + readonly agent: Endpoint3_4Request["payload"]["agent"] } -const Endpoint0_4 = (raw: RawClient["server.session"]) => (input: Endpoint0_4Input) => - raw["session.switchAgent"]({ params: { sessionID: input.sessionID }, payload: { agent: input.agent } }).pipe( +const Endpoint3_4 = (raw: RawClient["server.session"]) => (input: Endpoint3_4Input) => + raw["session.switchAgent"]({ params: { sessionID: input["sessionID"] }, payload: { agent: input["agent"] } }).pipe( Effect.mapError(mapClientError), ) -type Endpoint0_5Request = Parameters[0] -type Endpoint0_5Input = { - readonly sessionID: Endpoint0_5Request["params"]["sessionID"] - readonly model: Endpoint0_5Request["payload"]["model"] +type Endpoint3_5Request = Parameters[0] +type Endpoint3_5Input = { + readonly sessionID: Endpoint3_5Request["params"]["sessionID"] + readonly model: Endpoint3_5Request["payload"]["model"] } -const Endpoint0_5 = (raw: RawClient["server.session"]) => (input: Endpoint0_5Input) => - raw["session.switchModel"]({ params: { sessionID: input.sessionID }, payload: { model: input.model } }).pipe( +const Endpoint3_5 = (raw: RawClient["server.session"]) => (input: Endpoint3_5Input) => + raw["session.switchModel"]({ params: { sessionID: input["sessionID"] }, payload: { model: input["model"] } }).pipe( Effect.mapError(mapClientError), ) -type Endpoint0_6Request = Parameters[0] -type Endpoint0_6Input = { - readonly sessionID: Endpoint0_6Request["params"]["sessionID"] - readonly id?: Endpoint0_6Request["payload"]["id"] - readonly prompt: Endpoint0_6Request["payload"]["prompt"] - readonly delivery?: Endpoint0_6Request["payload"]["delivery"] - readonly resume?: Endpoint0_6Request["payload"]["resume"] +type Endpoint3_6Request = Parameters[0] +type Endpoint3_6Input = { + readonly sessionID: Endpoint3_6Request["params"]["sessionID"] + readonly id?: Endpoint3_6Request["payload"]["id"] + readonly prompt: Endpoint3_6Request["payload"]["prompt"] + readonly delivery?: Endpoint3_6Request["payload"]["delivery"] + readonly resume?: Endpoint3_6Request["payload"]["resume"] } -const Endpoint0_6 = (raw: RawClient["server.session"]) => (input: Endpoint0_6Input) => +const Endpoint3_6 = (raw: RawClient["server.session"]) => (input: Endpoint3_6Input) => raw["session.prompt"]({ - params: { sessionID: input.sessionID }, - payload: { id: input.id, prompt: input.prompt, delivery: input.delivery, resume: input.resume }, + params: { sessionID: input["sessionID"] }, + payload: { id: input["id"], prompt: input["prompt"], delivery: input["delivery"], resume: input["resume"] }, }).pipe( Effect.mapError(mapClientError), Effect.map((value) => value.data), ) -type Endpoint0_7Request = Parameters[0] -type Endpoint0_7Input = { readonly sessionID: Endpoint0_7Request["params"]["sessionID"] } -const Endpoint0_7 = (raw: RawClient["server.session"]) => (input: Endpoint0_7Input) => - raw["session.compact"]({ params: { sessionID: input.sessionID } }).pipe(Effect.mapError(mapClientError)) +type Endpoint3_7Request = Parameters[0] +type Endpoint3_7Input = { readonly sessionID: Endpoint3_7Request["params"]["sessionID"] } +const Endpoint3_7 = (raw: RawClient["server.session"]) => (input: Endpoint3_7Input) => + raw["session.compact"]({ params: { sessionID: input["sessionID"] } }).pipe(Effect.mapError(mapClientError)) -type Endpoint0_8Request = Parameters[0] -type Endpoint0_8Input = { readonly sessionID: Endpoint0_8Request["params"]["sessionID"] } -const Endpoint0_8 = (raw: RawClient["server.session"]) => (input: Endpoint0_8Input) => - raw["session.wait"]({ params: { sessionID: input.sessionID } }).pipe(Effect.mapError(mapClientError)) +type Endpoint3_8Request = Parameters[0] +type Endpoint3_8Input = { readonly sessionID: Endpoint3_8Request["params"]["sessionID"] } +const Endpoint3_8 = (raw: RawClient["server.session"]) => (input: Endpoint3_8Input) => + raw["session.wait"]({ params: { sessionID: input["sessionID"] } }).pipe(Effect.mapError(mapClientError)) -type Endpoint0_9Request = Parameters[0] -type Endpoint0_9Input = { - readonly sessionID: Endpoint0_9Request["params"]["sessionID"] - readonly messageID: Endpoint0_9Request["payload"]["messageID"] - readonly files?: Endpoint0_9Request["payload"]["files"] +type Endpoint3_9Request = Parameters[0] +type Endpoint3_9Input = { + readonly sessionID: Endpoint3_9Request["params"]["sessionID"] + readonly messageID: Endpoint3_9Request["payload"]["messageID"] + readonly files?: Endpoint3_9Request["payload"]["files"] } -const Endpoint0_9 = (raw: RawClient["server.session"]) => (input: Endpoint0_9Input) => +const Endpoint3_9 = (raw: RawClient["server.session"]) => (input: Endpoint3_9Input) => raw["session.revert.stage"]({ - params: { sessionID: input.sessionID }, - payload: { messageID: input.messageID, files: input.files }, + params: { sessionID: input["sessionID"] }, + payload: { messageID: input["messageID"], files: input["files"] }, }).pipe( Effect.mapError(mapClientError), Effect.map((value) => value.data), ) -type Endpoint0_10Request = Parameters[0] -type Endpoint0_10Input = { readonly sessionID: Endpoint0_10Request["params"]["sessionID"] } -const Endpoint0_10 = (raw: RawClient["server.session"]) => (input: Endpoint0_10Input) => - raw["session.revert.clear"]({ params: { sessionID: input.sessionID } }).pipe(Effect.mapError(mapClientError)) +type Endpoint3_10Request = Parameters[0] +type Endpoint3_10Input = { readonly sessionID: Endpoint3_10Request["params"]["sessionID"] } +const Endpoint3_10 = (raw: RawClient["server.session"]) => (input: Endpoint3_10Input) => + raw["session.revert.clear"]({ params: { sessionID: input["sessionID"] } }).pipe(Effect.mapError(mapClientError)) -type Endpoint0_11Request = Parameters[0] -type Endpoint0_11Input = { readonly sessionID: Endpoint0_11Request["params"]["sessionID"] } -const Endpoint0_11 = (raw: RawClient["server.session"]) => (input: Endpoint0_11Input) => - raw["session.revert.commit"]({ params: { sessionID: input.sessionID } }).pipe(Effect.mapError(mapClientError)) +type Endpoint3_11Request = Parameters[0] +type Endpoint3_11Input = { readonly sessionID: Endpoint3_11Request["params"]["sessionID"] } +const Endpoint3_11 = (raw: RawClient["server.session"]) => (input: Endpoint3_11Input) => + raw["session.revert.commit"]({ params: { sessionID: input["sessionID"] } }).pipe(Effect.mapError(mapClientError)) -type Endpoint0_12Request = Parameters[0] -type Endpoint0_12Input = { readonly sessionID: Endpoint0_12Request["params"]["sessionID"] } -const Endpoint0_12 = (raw: RawClient["server.session"]) => (input: Endpoint0_12Input) => - raw["session.context"]({ params: { sessionID: input.sessionID } }).pipe( +type Endpoint3_12Request = Parameters[0] +type Endpoint3_12Input = { readonly sessionID: Endpoint3_12Request["params"]["sessionID"] } +const Endpoint3_12 = (raw: RawClient["server.session"]) => (input: Endpoint3_12Input) => + raw["session.context"]({ params: { sessionID: input["sessionID"] } }).pipe( Effect.mapError(mapClientError), Effect.map((value) => value.data), ) -type Endpoint0_13Request = Parameters[0] -type Endpoint0_13Input = { - readonly sessionID: Endpoint0_13Request["params"]["sessionID"] - readonly limit?: Endpoint0_13Request["query"]["limit"] - readonly after?: Endpoint0_13Request["query"]["after"] +type Endpoint3_13Request = Parameters[0] +type Endpoint3_13Input = { + readonly sessionID: Endpoint3_13Request["params"]["sessionID"] + readonly limit?: Endpoint3_13Request["query"]["limit"] + readonly after?: Endpoint3_13Request["query"]["after"] } -const Endpoint0_13 = (raw: RawClient["server.session"]) => (input: Endpoint0_13Input) => +const Endpoint3_13 = (raw: RawClient["server.session"]) => (input: Endpoint3_13Input) => raw["session.history"]({ - params: { sessionID: input.sessionID }, - query: { limit: input.limit, after: input.after }, + params: { sessionID: input["sessionID"] }, + query: { limit: input["limit"], after: input["after"] }, }).pipe(Effect.mapError(mapClientError)) -type Endpoint0_14Request = Parameters[0] -type Endpoint0_14Input = { - readonly sessionID: Endpoint0_14Request["params"]["sessionID"] - readonly after?: Endpoint0_14Request["query"]["after"] +type Endpoint3_14Request = Parameters[0] +type Endpoint3_14Input = { + readonly sessionID: Endpoint3_14Request["params"]["sessionID"] + readonly after?: Endpoint3_14Request["query"]["after"] } -const Endpoint0_14 = (raw: RawClient["server.session"]) => (input: Endpoint0_14Input) => +const Endpoint3_14 = (raw: RawClient["server.session"]) => (input: Endpoint3_14Input) => Stream.unwrap( - raw["session.events"]({ params: { sessionID: input.sessionID }, query: { after: input.after } }).pipe( + raw["session.events"]({ params: { sessionID: input["sessionID"] }, query: { after: input["after"] } }).pipe( Effect.mapError(mapClientError), Effect.map((stream) => stream.pipe(Stream.mapError(mapClientError))), ), ) -type Endpoint0_15Request = Parameters[0] -type Endpoint0_15Input = { readonly sessionID: Endpoint0_15Request["params"]["sessionID"] } -const Endpoint0_15 = (raw: RawClient["server.session"]) => (input: Endpoint0_15Input) => - raw["session.interrupt"]({ params: { sessionID: input.sessionID } }).pipe(Effect.mapError(mapClientError)) +type Endpoint3_15Request = Parameters[0] +type Endpoint3_15Input = { readonly sessionID: Endpoint3_15Request["params"]["sessionID"] } +const Endpoint3_15 = (raw: RawClient["server.session"]) => (input: Endpoint3_15Input) => + raw["session.interrupt"]({ params: { sessionID: input["sessionID"] } }).pipe(Effect.mapError(mapClientError)) -type Endpoint0_16Request = Parameters[0] -type Endpoint0_16Input = { - readonly sessionID: Endpoint0_16Request["params"]["sessionID"] - readonly messageID: Endpoint0_16Request["params"]["messageID"] +type Endpoint3_16Request = Parameters[0] +type Endpoint3_16Input = { + readonly sessionID: Endpoint3_16Request["params"]["sessionID"] + readonly messageID: Endpoint3_16Request["params"]["messageID"] } -const Endpoint0_16 = (raw: RawClient["server.session"]) => (input: Endpoint0_16Input) => - raw["session.message"]({ params: { sessionID: input.sessionID, messageID: input.messageID } }).pipe( +const Endpoint3_16 = (raw: RawClient["server.session"]) => (input: Endpoint3_16Input) => + raw["session.message"]({ params: { sessionID: input["sessionID"], messageID: input["messageID"] } }).pipe( Effect.mapError(mapClientError), Effect.map((value) => value.data), ) -const adaptGroup0 = (raw: RawClient["server.session"]) => ({ - list: Endpoint0_0(raw), - create: Endpoint0_1(raw), - active: Endpoint0_2(raw), - get: Endpoint0_3(raw), - switchAgent: Endpoint0_4(raw), - switchModel: Endpoint0_5(raw), - prompt: Endpoint0_6(raw), - compact: Endpoint0_7(raw), - wait: Endpoint0_8(raw), - stage: Endpoint0_9(raw), - clear: Endpoint0_10(raw), - commit: Endpoint0_11(raw), - context: Endpoint0_12(raw), - history: Endpoint0_13(raw), - events: Endpoint0_14(raw), - interrupt: Endpoint0_15(raw), - message: Endpoint0_16(raw), +const adaptGroup3 = (raw: RawClient["server.session"]) => ({ + list: Endpoint3_0(raw), + create: Endpoint3_1(raw), + active: Endpoint3_2(raw), + get: Endpoint3_3(raw), + switchAgent: Endpoint3_4(raw), + switchModel: Endpoint3_5(raw), + prompt: Endpoint3_6(raw), + compact: Endpoint3_7(raw), + wait: Endpoint3_8(raw), + stage: Endpoint3_9(raw), + clear: Endpoint3_10(raw), + commit: Endpoint3_11(raw), + context: Endpoint3_12(raw), + history: Endpoint3_13(raw), + events: Endpoint3_14(raw), + interrupt: Endpoint3_15(raw), + message: Endpoint3_16(raw), +}) + +type Endpoint4_0Request = Parameters[0] +type Endpoint4_0Input = { + readonly sessionID: Endpoint4_0Request["params"]["sessionID"] + readonly limit?: Endpoint4_0Request["query"]["limit"] + readonly order?: Endpoint4_0Request["query"]["order"] + readonly cursor?: Endpoint4_0Request["query"]["cursor"] +} +const Endpoint4_0 = (raw: RawClient["server.message"]) => (input: Endpoint4_0Input) => + raw["session.messages"]({ + params: { sessionID: input["sessionID"] }, + query: { limit: input["limit"], order: input["order"], cursor: input["cursor"] }, + }).pipe(Effect.mapError(mapClientError)) + +const adaptGroup4 = (raw: RawClient["server.message"]) => ({ list: Endpoint4_0(raw) }) + +type Endpoint5_0Request = Parameters[0] +type Endpoint5_0Input = { readonly location?: Endpoint5_0Request["query"]["location"] } +const Endpoint5_0 = (raw: RawClient["server.model"]) => (input?: Endpoint5_0Input) => + raw["model.list"]({ query: { location: input?.["location"] } }).pipe(Effect.mapError(mapClientError)) + +const adaptGroup5 = (raw: RawClient["server.model"]) => ({ list: Endpoint5_0(raw) }) + +type Endpoint6_0Request = Parameters[0] +type Endpoint6_0Input = { readonly location?: Endpoint6_0Request["query"]["location"] } +const Endpoint6_0 = (raw: RawClient["server.provider"]) => (input?: Endpoint6_0Input) => + raw["provider.list"]({ query: { location: input?.["location"] } }).pipe(Effect.mapError(mapClientError)) + +type Endpoint6_1Request = Parameters[0] +type Endpoint6_1Input = { + readonly providerID: Endpoint6_1Request["params"]["providerID"] + readonly location?: Endpoint6_1Request["query"]["location"] +} +const Endpoint6_1 = (raw: RawClient["server.provider"]) => (input: Endpoint6_1Input) => + raw["provider.get"]({ params: { providerID: input["providerID"] }, query: { location: input["location"] } }).pipe( + Effect.mapError(mapClientError), + ) + +const adaptGroup6 = (raw: RawClient["server.provider"]) => ({ list: Endpoint6_0(raw), get: Endpoint6_1(raw) }) + +type Endpoint7_0Request = Parameters[0] +type Endpoint7_0Input = { readonly location?: Endpoint7_0Request["query"]["location"] } +const Endpoint7_0 = (raw: RawClient["server.integration"]) => (input?: Endpoint7_0Input) => + raw["integration.list"]({ query: { location: input?.["location"] } }).pipe(Effect.mapError(mapClientError)) + +type Endpoint7_1Request = Parameters[0] +type Endpoint7_1Input = { + readonly integrationID: Endpoint7_1Request["params"]["integrationID"] + readonly location?: Endpoint7_1Request["query"]["location"] +} +const Endpoint7_1 = (raw: RawClient["server.integration"]) => (input: Endpoint7_1Input) => + raw["integration.get"]({ + params: { integrationID: input["integrationID"] }, + query: { location: input["location"] }, + }).pipe(Effect.mapError(mapClientError)) + +type Endpoint7_2Request = Parameters[0] +type Endpoint7_2Input = { + readonly integrationID: Endpoint7_2Request["params"]["integrationID"] + readonly location?: Endpoint7_2Request["query"]["location"] + readonly key: Endpoint7_2Request["payload"]["key"] + readonly label?: Endpoint7_2Request["payload"]["label"] +} +const Endpoint7_2 = (raw: RawClient["server.integration"]) => (input: Endpoint7_2Input) => + raw["integration.connect.key"]({ + params: { integrationID: input["integrationID"] }, + query: { location: input["location"] }, + payload: { key: input["key"], label: input["label"] }, + }).pipe(Effect.mapError(mapClientError)) + +type Endpoint7_3Request = Parameters[0] +type Endpoint7_3Input = { + readonly integrationID: Endpoint7_3Request["params"]["integrationID"] + readonly location?: Endpoint7_3Request["query"]["location"] + readonly methodID: Endpoint7_3Request["payload"]["methodID"] + readonly inputs: Endpoint7_3Request["payload"]["inputs"] + readonly label?: Endpoint7_3Request["payload"]["label"] +} +const Endpoint7_3 = (raw: RawClient["server.integration"]) => (input: Endpoint7_3Input) => + raw["integration.connect.oauth"]({ + params: { integrationID: input["integrationID"] }, + query: { location: input["location"] }, + payload: { methodID: input["methodID"], inputs: input["inputs"], label: input["label"] }, + }).pipe(Effect.mapError(mapClientError)) + +type Endpoint7_4Request = Parameters[0] +type Endpoint7_4Input = { + readonly attemptID: Endpoint7_4Request["params"]["attemptID"] + readonly location?: Endpoint7_4Request["query"]["location"] +} +const Endpoint7_4 = (raw: RawClient["server.integration"]) => (input: Endpoint7_4Input) => + raw["integration.attempt.status"]({ + params: { attemptID: input["attemptID"] }, + query: { location: input["location"] }, + }).pipe(Effect.mapError(mapClientError)) + +type Endpoint7_5Request = Parameters[0] +type Endpoint7_5Input = { + readonly attemptID: Endpoint7_5Request["params"]["attemptID"] + readonly location?: Endpoint7_5Request["query"]["location"] + readonly code?: Endpoint7_5Request["payload"]["code"] +} +const Endpoint7_5 = (raw: RawClient["server.integration"]) => (input: Endpoint7_5Input) => + raw["integration.attempt.complete"]({ + params: { attemptID: input["attemptID"] }, + query: { location: input["location"] }, + payload: { code: input["code"] }, + }).pipe(Effect.mapError(mapClientError)) + +type Endpoint7_6Request = Parameters[0] +type Endpoint7_6Input = { + readonly attemptID: Endpoint7_6Request["params"]["attemptID"] + readonly location?: Endpoint7_6Request["query"]["location"] +} +const Endpoint7_6 = (raw: RawClient["server.integration"]) => (input: Endpoint7_6Input) => + raw["integration.attempt.cancel"]({ + params: { attemptID: input["attemptID"] }, + query: { location: input["location"] }, + }).pipe(Effect.mapError(mapClientError)) + +const adaptGroup7 = (raw: RawClient["server.integration"]) => ({ + list: Endpoint7_0(raw), + get: Endpoint7_1(raw), + connectKey: Endpoint7_2(raw), + connectOauth: Endpoint7_3(raw), + attemptStatus: Endpoint7_4(raw), + attemptComplete: Endpoint7_5(raw), + attemptCancel: Endpoint7_6(raw), }) -const Endpoint1_0 = (raw: RawClient["server.event"]) => () => +type Endpoint8_0Request = Parameters[0] +type Endpoint8_0Input = { + readonly credentialID: Endpoint8_0Request["params"]["credentialID"] + readonly location?: Endpoint8_0Request["query"]["location"] + readonly label: Endpoint8_0Request["payload"]["label"] +} +const Endpoint8_0 = (raw: RawClient["server.credential"]) => (input: Endpoint8_0Input) => + raw["credential.update"]({ + params: { credentialID: input["credentialID"] }, + query: { location: input["location"] }, + payload: { label: input["label"] }, + }).pipe(Effect.mapError(mapClientError)) + +type Endpoint8_1Request = Parameters[0] +type Endpoint8_1Input = { + readonly credentialID: Endpoint8_1Request["params"]["credentialID"] + readonly location?: Endpoint8_1Request["query"]["location"] +} +const Endpoint8_1 = (raw: RawClient["server.credential"]) => (input: Endpoint8_1Input) => + raw["credential.remove"]({ + params: { credentialID: input["credentialID"] }, + query: { location: input["location"] }, + }).pipe(Effect.mapError(mapClientError)) + +const adaptGroup8 = (raw: RawClient["server.credential"]) => ({ update: Endpoint8_0(raw), remove: Endpoint8_1(raw) }) + +type Endpoint9_0Request = Parameters[0] +type Endpoint9_0Input = { readonly location?: Endpoint9_0Request["query"]["location"] } +const Endpoint9_0 = (raw: RawClient["server.permission"]) => (input?: Endpoint9_0Input) => + raw["permission.request.list"]({ query: { location: input?.["location"] } }).pipe(Effect.mapError(mapClientError)) + +type Endpoint9_1Request = Parameters[0] +type Endpoint9_1Input = { readonly projectID?: Endpoint9_1Request["query"]["projectID"] } +const Endpoint9_1 = (raw: RawClient["server.permission"]) => (input?: Endpoint9_1Input) => + raw["permission.saved.list"]({ query: { projectID: input?.["projectID"] } }).pipe( + Effect.mapError(mapClientError), + Effect.map((value) => value.data), + ) + +type Endpoint9_2Request = Parameters[0] +type Endpoint9_2Input = { readonly id: Endpoint9_2Request["params"]["id"] } +const Endpoint9_2 = (raw: RawClient["server.permission"]) => (input: Endpoint9_2Input) => + raw["permission.saved.remove"]({ params: { id: input["id"] } }).pipe(Effect.mapError(mapClientError)) + +type Endpoint9_3Request = Parameters[0] +type Endpoint9_3Input = { + readonly sessionID: Endpoint9_3Request["params"]["sessionID"] + readonly id?: Endpoint9_3Request["payload"]["id"] + readonly action: Endpoint9_3Request["payload"]["action"] + readonly resources: Endpoint9_3Request["payload"]["resources"] + readonly save?: Endpoint9_3Request["payload"]["save"] + readonly metadata?: Endpoint9_3Request["payload"]["metadata"] + readonly source?: Endpoint9_3Request["payload"]["source"] + readonly agent?: Endpoint9_3Request["payload"]["agent"] +} +const Endpoint9_3 = (raw: RawClient["server.permission"]) => (input: Endpoint9_3Input) => + raw["session.permission.create"]({ + params: { sessionID: input["sessionID"] }, + payload: { + id: input["id"], + action: input["action"], + resources: input["resources"], + save: input["save"], + metadata: input["metadata"], + source: input["source"], + agent: input["agent"], + }, + }).pipe( + Effect.mapError(mapClientError), + Effect.map((value) => value.data), + ) + +type Endpoint9_4Request = Parameters[0] +type Endpoint9_4Input = { readonly sessionID: Endpoint9_4Request["params"]["sessionID"] } +const Endpoint9_4 = (raw: RawClient["server.permission"]) => (input: Endpoint9_4Input) => + raw["session.permission.list"]({ params: { sessionID: input["sessionID"] } }).pipe( + Effect.mapError(mapClientError), + Effect.map((value) => value.data), + ) + +type Endpoint9_5Request = Parameters[0] +type Endpoint9_5Input = { + readonly sessionID: Endpoint9_5Request["params"]["sessionID"] + readonly requestID: Endpoint9_5Request["params"]["requestID"] +} +const Endpoint9_5 = (raw: RawClient["server.permission"]) => (input: Endpoint9_5Input) => + raw["session.permission.get"]({ params: { sessionID: input["sessionID"], requestID: input["requestID"] } }).pipe( + Effect.mapError(mapClientError), + Effect.map((value) => value.data), + ) + +type Endpoint9_6Request = Parameters[0] +type Endpoint9_6Input = { + readonly sessionID: Endpoint9_6Request["params"]["sessionID"] + readonly requestID: Endpoint9_6Request["params"]["requestID"] + readonly reply: Endpoint9_6Request["payload"]["reply"] + readonly message?: Endpoint9_6Request["payload"]["message"] +} +const Endpoint9_6 = (raw: RawClient["server.permission"]) => (input: Endpoint9_6Input) => + raw["session.permission.reply"]({ + params: { sessionID: input["sessionID"], requestID: input["requestID"] }, + payload: { reply: input["reply"], message: input["message"] }, + }).pipe(Effect.mapError(mapClientError)) + +const adaptGroup9 = (raw: RawClient["server.permission"]) => ({ + listRequests: Endpoint9_0(raw), + listSaved: Endpoint9_1(raw), + removeSaved: Endpoint9_2(raw), + create: Endpoint9_3(raw), + list: Endpoint9_4(raw), + get: Endpoint9_5(raw), + reply: Endpoint9_6(raw), +}) + +type Endpoint10_0Request = Parameters[0] +type Endpoint10_0Input = { + readonly location?: Endpoint10_0Request["query"]["location"] + readonly path?: Endpoint10_0Request["query"]["path"] +} +const Endpoint10_0 = (raw: RawClient["server.fs"]) => (input?: Endpoint10_0Input) => + raw["fs.list"]({ query: { location: input?.["location"], path: input?.["path"] } }).pipe( + Effect.mapError(mapClientError), + ) + +type Endpoint10_1Request = Parameters[0] +type Endpoint10_1Input = { + readonly location?: Endpoint10_1Request["query"]["location"] + readonly query: Endpoint10_1Request["query"]["query"] + readonly type?: Endpoint10_1Request["query"]["type"] + readonly limit?: Endpoint10_1Request["query"]["limit"] +} +const Endpoint10_1 = (raw: RawClient["server.fs"]) => (input: Endpoint10_1Input) => + raw["fs.find"]({ + query: { location: input["location"], query: input["query"], type: input["type"], limit: input["limit"] }, + }).pipe(Effect.mapError(mapClientError)) + +const adaptGroup10 = (raw: RawClient["server.fs"]) => ({ list: Endpoint10_0(raw), find: Endpoint10_1(raw) }) + +type Endpoint11_0Request = Parameters[0] +type Endpoint11_0Input = { readonly location?: Endpoint11_0Request["query"]["location"] } +const Endpoint11_0 = (raw: RawClient["server.command"]) => (input?: Endpoint11_0Input) => + raw["command.list"]({ query: { location: input?.["location"] } }).pipe(Effect.mapError(mapClientError)) + +const adaptGroup11 = (raw: RawClient["server.command"]) => ({ list: Endpoint11_0(raw) }) + +type Endpoint12_0Request = Parameters[0] +type Endpoint12_0Input = { readonly location?: Endpoint12_0Request["query"]["location"] } +const Endpoint12_0 = (raw: RawClient["server.skill"]) => (input?: Endpoint12_0Input) => + raw["skill.list"]({ query: { location: input?.["location"] } }).pipe(Effect.mapError(mapClientError)) + +const adaptGroup12 = (raw: RawClient["server.skill"]) => ({ list: Endpoint12_0(raw) }) + +const Endpoint13_0 = (raw: RawClient["server.event"]) => () => Stream.unwrap( raw["event.subscribe"]({}).pipe( Effect.mapError(mapClientError), @@ -216,11 +516,190 @@ const Endpoint1_0 = (raw: RawClient["server.event"]) => () => ), ) -const adaptGroup1 = (raw: RawClient["server.event"]) => ({ subscribe: Endpoint1_0(raw) }) +const adaptGroup13 = (raw: RawClient["server.event"]) => ({ subscribe: Endpoint13_0(raw) }) + +type Endpoint14_0Request = Parameters[0] +type Endpoint14_0Input = { readonly location?: Endpoint14_0Request["query"]["location"] } +const Endpoint14_0 = (raw: RawClient["server.pty"]) => (input?: Endpoint14_0Input) => + raw["pty.list"]({ query: { location: input?.["location"] } }).pipe(Effect.mapError(mapClientError)) + +type Endpoint14_1Request = Parameters[0] +type Endpoint14_1Input = { + readonly location?: Endpoint14_1Request["query"]["location"] + readonly command?: Endpoint14_1Request["payload"]["command"] + readonly args?: Endpoint14_1Request["payload"]["args"] + readonly cwd?: Endpoint14_1Request["payload"]["cwd"] + readonly title?: Endpoint14_1Request["payload"]["title"] + readonly env?: Endpoint14_1Request["payload"]["env"] +} +const Endpoint14_1 = (raw: RawClient["server.pty"]) => (input?: Endpoint14_1Input) => + raw["pty.create"]({ + query: { location: input?.["location"] }, + payload: { + command: input?.["command"], + args: input?.["args"], + cwd: input?.["cwd"], + title: input?.["title"], + env: input?.["env"], + }, + }).pipe(Effect.mapError(mapClientError)) + +type Endpoint14_2Request = Parameters[0] +type Endpoint14_2Input = { + readonly ptyID: Endpoint14_2Request["params"]["ptyID"] + readonly location?: Endpoint14_2Request["query"]["location"] +} +const Endpoint14_2 = (raw: RawClient["server.pty"]) => (input: Endpoint14_2Input) => + raw["pty.get"]({ params: { ptyID: input["ptyID"] }, query: { location: input["location"] } }).pipe( + Effect.mapError(mapClientError), + ) + +type Endpoint14_3Request = Parameters[0] +type Endpoint14_3Input = { + readonly ptyID: Endpoint14_3Request["params"]["ptyID"] + readonly location?: Endpoint14_3Request["query"]["location"] + readonly title?: Endpoint14_3Request["payload"]["title"] + readonly size?: Endpoint14_3Request["payload"]["size"] +} +const Endpoint14_3 = (raw: RawClient["server.pty"]) => (input: Endpoint14_3Input) => + raw["pty.update"]({ + params: { ptyID: input["ptyID"] }, + query: { location: input["location"] }, + payload: { title: input["title"], size: input["size"] }, + }).pipe(Effect.mapError(mapClientError)) + +type Endpoint14_4Request = Parameters[0] +type Endpoint14_4Input = { + readonly ptyID: Endpoint14_4Request["params"]["ptyID"] + readonly location?: Endpoint14_4Request["query"]["location"] +} +const Endpoint14_4 = (raw: RawClient["server.pty"]) => (input: Endpoint14_4Input) => + raw["pty.remove"]({ params: { ptyID: input["ptyID"] }, query: { location: input["location"] } }).pipe( + Effect.mapError(mapClientError), + ) + +const adaptGroup14 = (raw: RawClient["server.pty"]) => ({ + list: Endpoint14_0(raw), + create: Endpoint14_1(raw), + get: Endpoint14_2(raw), + update: Endpoint14_3(raw), + remove: Endpoint14_4(raw), +}) + +type Endpoint15_0Request = Parameters[0] +type Endpoint15_0Input = { readonly location?: Endpoint15_0Request["query"]["location"] } +const Endpoint15_0 = (raw: RawClient["server.question"]) => (input?: Endpoint15_0Input) => + raw["question.request.list"]({ query: { location: input?.["location"] } }).pipe(Effect.mapError(mapClientError)) + +type Endpoint15_1Request = Parameters[0] +type Endpoint15_1Input = { readonly sessionID: Endpoint15_1Request["params"]["sessionID"] } +const Endpoint15_1 = (raw: RawClient["server.question"]) => (input: Endpoint15_1Input) => + raw["session.question.list"]({ params: { sessionID: input["sessionID"] } }).pipe( + Effect.mapError(mapClientError), + Effect.map((value) => value.data), + ) + +type Endpoint15_2Request = Parameters[0] +type Endpoint15_2Input = { + readonly sessionID: Endpoint15_2Request["params"]["sessionID"] + readonly requestID: Endpoint15_2Request["params"]["requestID"] + readonly answers: Endpoint15_2Request["payload"]["answers"] +} +const Endpoint15_2 = (raw: RawClient["server.question"]) => (input: Endpoint15_2Input) => + raw["session.question.reply"]({ + params: { sessionID: input["sessionID"], requestID: input["requestID"] }, + payload: { answers: input["answers"] }, + }).pipe(Effect.mapError(mapClientError)) + +type Endpoint15_3Request = Parameters[0] +type Endpoint15_3Input = { + readonly sessionID: Endpoint15_3Request["params"]["sessionID"] + readonly requestID: Endpoint15_3Request["params"]["requestID"] +} +const Endpoint15_3 = (raw: RawClient["server.question"]) => (input: Endpoint15_3Input) => + raw["session.question.reject"]({ params: { sessionID: input["sessionID"], requestID: input["requestID"] } }).pipe( + Effect.mapError(mapClientError), + ) + +const adaptGroup15 = (raw: RawClient["server.question"]) => ({ + listRequests: Endpoint15_0(raw), + list: Endpoint15_1(raw), + reply: Endpoint15_2(raw), + reject: Endpoint15_3(raw), +}) + +type Endpoint16_0Request = Parameters[0] +type Endpoint16_0Input = { readonly location?: Endpoint16_0Request["query"]["location"] } +const Endpoint16_0 = (raw: RawClient["server.reference"]) => (input?: Endpoint16_0Input) => + raw["reference.list"]({ query: { location: input?.["location"] } }).pipe(Effect.mapError(mapClientError)) + +const adaptGroup16 = (raw: RawClient["server.reference"]) => ({ list: Endpoint16_0(raw) }) + +type Endpoint17_0Request = Parameters[0] +type Endpoint17_0Input = { + readonly projectID: Endpoint17_0Request["params"]["projectID"] + readonly location?: Endpoint17_0Request["query"]["location"] + readonly strategy: Endpoint17_0Request["payload"]["strategy"] + readonly directory: Endpoint17_0Request["payload"]["directory"] + readonly name?: Endpoint17_0Request["payload"]["name"] +} +const Endpoint17_0 = (raw: RawClient["server.projectCopy"]) => (input: Endpoint17_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 Endpoint17_1Request = Parameters[0] +type Endpoint17_1Input = { + readonly projectID: Endpoint17_1Request["params"]["projectID"] + readonly location?: Endpoint17_1Request["query"]["location"] + readonly directory: Endpoint17_1Request["payload"]["directory"] + readonly force: Endpoint17_1Request["payload"]["force"] +} +const Endpoint17_1 = (raw: RawClient["server.projectCopy"]) => (input: Endpoint17_1Input) => + raw["projectCopy.remove"]({ + params: { projectID: input["projectID"] }, + query: { location: input["location"] }, + payload: { directory: input["directory"], force: input["force"] }, + }).pipe(Effect.mapError(mapClientError)) + +type Endpoint17_2Request = Parameters[0] +type Endpoint17_2Input = { + readonly projectID: Endpoint17_2Request["params"]["projectID"] + readonly location?: Endpoint17_2Request["query"]["location"] +} +const Endpoint17_2 = (raw: RawClient["server.projectCopy"]) => (input: Endpoint17_2Input) => + raw["projectCopy.refresh"]({ + params: { projectID: input["projectID"] }, + query: { location: input["location"] }, + }).pipe(Effect.mapError(mapClientError)) + +const adaptGroup17 = (raw: RawClient["server.projectCopy"]) => ({ + create: Endpoint17_0(raw), + remove: Endpoint17_1(raw), + refresh: Endpoint17_2(raw), +}) const adaptClient = (raw: RawClient) => ({ - sessions: adaptGroup0(raw["server.session"]), - events: adaptGroup1(raw["server.event"]), + health: adaptGroup0(raw["server.health"]), + location: adaptGroup1(raw["server.location"]), + agents: adaptGroup2(raw["server.agent"]), + sessions: adaptGroup3(raw["server.session"]), + messages: adaptGroup4(raw["server.message"]), + models: adaptGroup5(raw["server.model"]), + providers: adaptGroup6(raw["server.provider"]), + integrations: adaptGroup7(raw["server.integration"]), + credentials: adaptGroup8(raw["server.credential"]), + permissions: adaptGroup9(raw["server.permission"]), + files: adaptGroup10(raw["server.fs"]), + commands: adaptGroup11(raw["server.command"]), + skills: adaptGroup12(raw["server.skill"]), + events: adaptGroup13(raw["server.event"]), + ptys: adaptGroup14(raw["server.pty"]), + questions: adaptGroup15(raw["server.question"]), + references: adaptGroup16(raw["server.reference"]), + projectCopies: adaptGroup17(raw["server.projectCopy"]), }) export const make = (options?: { readonly baseUrl?: URL | string }) => diff --git a/packages/client/src/generated/client.ts b/packages/client/src/generated/client.ts index c14015f11ce5..27ec3d81ba2c 100644 --- a/packages/client/src/generated/client.ts +++ b/packages/client/src/generated/client.ts @@ -1,4 +1,9 @@ import type { + HealthGetOutput, + LocationGetInput, + LocationGetOutput, + AgentsListInput, + AgentsListOutput, SessionsListInput, SessionsListOutput, SessionsCreateInput, @@ -32,7 +37,81 @@ import type { SessionsInterruptOutput, SessionsMessageInput, SessionsMessageOutput, + MessagesListInput, + MessagesListOutput, + ModelsListInput, + ModelsListOutput, + ProvidersListInput, + ProvidersListOutput, + ProvidersGetInput, + ProvidersGetOutput, + IntegrationsListInput, + IntegrationsListOutput, + IntegrationsGetInput, + IntegrationsGetOutput, + IntegrationsConnectKeyInput, + IntegrationsConnectKeyOutput, + IntegrationsConnectOauthInput, + IntegrationsConnectOauthOutput, + IntegrationsAttemptStatusInput, + IntegrationsAttemptStatusOutput, + IntegrationsAttemptCompleteInput, + IntegrationsAttemptCompleteOutput, + IntegrationsAttemptCancelInput, + IntegrationsAttemptCancelOutput, + CredentialsUpdateInput, + CredentialsUpdateOutput, + CredentialsRemoveInput, + CredentialsRemoveOutput, + PermissionsListRequestsInput, + PermissionsListRequestsOutput, + PermissionsListSavedInput, + PermissionsListSavedOutput, + PermissionsRemoveSavedInput, + PermissionsRemoveSavedOutput, + PermissionsCreateInput, + PermissionsCreateOutput, + PermissionsListInput, + PermissionsListOutput, + PermissionsGetInput, + PermissionsGetOutput, + PermissionsReplyInput, + PermissionsReplyOutput, + FilesListInput, + FilesListOutput, + FilesFindInput, + FilesFindOutput, + CommandsListInput, + CommandsListOutput, + SkillsListInput, + SkillsListOutput, EventsSubscribeOutput, + PtysListInput, + PtysListOutput, + PtysCreateInput, + PtysCreateOutput, + PtysGetInput, + PtysGetOutput, + PtysUpdateInput, + PtysUpdateOutput, + PtysRemoveInput, + PtysRemoveOutput, + QuestionsListRequestsInput, + QuestionsListRequestsOutput, + QuestionsListInput, + QuestionsListOutput, + QuestionsReplyInput, + QuestionsReplyOutput, + QuestionsRejectInput, + QuestionsRejectOutput, + ReferencesListInput, + ReferencesListOutput, + ProjectCopiesCreateInput, + ProjectCopiesCreateOutput, + ProjectCopiesRemoveInput, + ProjectCopiesRemoveOutput, + ProjectCopiesRefreshInput, + ProjectCopiesRefreshOutput, } from "./types" import { ClientError } from "./client-error" @@ -168,6 +247,41 @@ export function make(options: ClientOptions) { }) return { + health: { + get: (requestOptions?: RequestOptions) => + request( + { method: "GET", path: `/api/health`, successStatus: 200, declaredStatuses: [401, 400], empty: false }, + requestOptions, + ), + }, + location: { + get: (input?: LocationGetInput, requestOptions?: RequestOptions) => + request( + { + method: "GET", + path: `/api/location`, + query: { location: input?.["location"] }, + successStatus: 200, + declaredStatuses: [401, 400], + empty: false, + }, + requestOptions, + ), + }, + agents: { + list: (input?: AgentsListInput, requestOptions?: RequestOptions) => + request( + { + method: "GET", + path: `/api/agent`, + query: { location: input?.["location"] }, + successStatus: 200, + declaredStatuses: [401, 400], + empty: false, + }, + requestOptions, + ), + }, sessions: { list: (input?: SessionsListInput, requestOptions?: RequestOptions) => request( @@ -175,14 +289,14 @@ export function make(options: ClientOptions) { method: "GET", path: `/api/session`, query: { - workspace: input?.workspace, - limit: input?.limit, - order: input?.order, - search: input?.search, - directory: input?.directory, - project: input?.project, - subpath: input?.subpath, - cursor: input?.cursor, + workspace: input?.["workspace"], + limit: input?.["limit"], + order: input?.["order"], + search: input?.["search"], + directory: input?.["directory"], + project: input?.["project"], + subpath: input?.["subpath"], + cursor: input?.["cursor"], }, successStatus: 200, declaredStatuses: [400, 401], @@ -195,7 +309,12 @@ export function make(options: ClientOptions) { { method: "POST", path: `/api/session`, - body: { id: input?.id, agent: input?.agent, model: input?.model, location: input?.location }, + body: { + id: input?.["id"], + agent: input?.["agent"], + model: input?.["model"], + location: input?.["location"], + }, successStatus: 200, declaredStatuses: [401, 400], empty: false, @@ -229,7 +348,7 @@ export function make(options: ClientOptions) { { method: "POST", path: `/api/session/${encodeURIComponent(input.sessionID)}/agent`, - body: { agent: input.agent }, + body: { agent: input["agent"] }, successStatus: 204, declaredStatuses: [404, 400, 401], empty: true, @@ -241,7 +360,7 @@ export function make(options: ClientOptions) { { method: "POST", path: `/api/session/${encodeURIComponent(input.sessionID)}/model`, - body: { model: input.model }, + body: { model: input["model"] }, successStatus: 204, declaredStatuses: [404, 400, 401], empty: true, @@ -253,7 +372,7 @@ export function make(options: ClientOptions) { { method: "POST", path: `/api/session/${encodeURIComponent(input.sessionID)}/prompt`, - body: { id: input.id, prompt: input.prompt, delivery: input.delivery, resume: input.resume }, + body: { id: input["id"], prompt: input["prompt"], delivery: input["delivery"], resume: input["resume"] }, successStatus: 200, declaredStatuses: [409, 404, 400, 401], empty: false, @@ -287,7 +406,7 @@ export function make(options: ClientOptions) { { method: "POST", path: `/api/session/${encodeURIComponent(input.sessionID)}/revert/stage`, - body: { messageID: input.messageID, files: input.files }, + body: { messageID: input["messageID"], files: input["files"] }, successStatus: 200, declaredStatuses: [404, 500, 400, 401], empty: false, @@ -332,7 +451,7 @@ export function make(options: ClientOptions) { { method: "GET", path: `/api/session/${encodeURIComponent(input.sessionID)}/history`, - query: { limit: input.limit, after: input.after }, + query: { limit: input["limit"], after: input["after"] }, successStatus: 200, declaredStatuses: [404, 400, 401], empty: false, @@ -344,7 +463,7 @@ export function make(options: ClientOptions) { { method: "GET", path: `/api/session/${encodeURIComponent(input.sessionID)}/event`, - query: { after: input.after }, + query: { after: input["after"] }, successStatus: 200, declaredStatuses: [404, 400, 401], empty: false, @@ -374,6 +493,321 @@ export function make(options: ClientOptions) { requestOptions, ).then((value) => value.data), }, + messages: { + list: (input: MessagesListInput, requestOptions?: RequestOptions) => + request( + { + method: "GET", + path: `/api/session/${encodeURIComponent(input.sessionID)}/message`, + query: { limit: input["limit"], order: input["order"], cursor: input["cursor"] }, + successStatus: 200, + declaredStatuses: [400, 404, 500, 401], + empty: false, + }, + requestOptions, + ), + }, + models: { + list: (input?: ModelsListInput, requestOptions?: RequestOptions) => + request( + { + method: "GET", + path: `/api/model`, + query: { location: input?.["location"] }, + successStatus: 200, + declaredStatuses: [503, 401, 400], + empty: false, + }, + requestOptions, + ), + }, + providers: { + list: (input?: ProvidersListInput, requestOptions?: RequestOptions) => + request( + { + method: "GET", + path: `/api/provider`, + query: { location: input?.["location"] }, + successStatus: 200, + declaredStatuses: [503, 401, 400], + empty: false, + }, + requestOptions, + ), + get: (input: ProvidersGetInput, requestOptions?: RequestOptions) => + request( + { + method: "GET", + path: `/api/provider/${encodeURIComponent(input.providerID)}`, + query: { location: input["location"] }, + successStatus: 200, + declaredStatuses: [404, 503, 401, 400], + empty: false, + }, + requestOptions, + ), + }, + integrations: { + list: (input?: IntegrationsListInput, requestOptions?: RequestOptions) => + request( + { + method: "GET", + path: `/api/integration`, + query: { location: input?.["location"] }, + successStatus: 200, + declaredStatuses: [401, 400], + empty: false, + }, + requestOptions, + ), + get: (input: IntegrationsGetInput, requestOptions?: RequestOptions) => + request( + { + method: "GET", + path: `/api/integration/${encodeURIComponent(input.integrationID)}`, + query: { location: input["location"] }, + successStatus: 200, + declaredStatuses: [401, 400], + empty: false, + }, + requestOptions, + ), + connectKey: (input: IntegrationsConnectKeyInput, requestOptions?: RequestOptions) => + request( + { + method: "POST", + path: `/api/integration/${encodeURIComponent(input.integrationID)}/connect/key`, + query: { location: input["location"] }, + body: { key: input["key"], label: input["label"] }, + successStatus: 204, + declaredStatuses: [400, 401], + empty: true, + }, + requestOptions, + ), + connectOauth: (input: IntegrationsConnectOauthInput, requestOptions?: RequestOptions) => + request( + { + method: "POST", + path: `/api/integration/${encodeURIComponent(input.integrationID)}/connect/oauth`, + query: { location: input["location"] }, + body: { methodID: input["methodID"], inputs: input["inputs"], label: input["label"] }, + successStatus: 200, + declaredStatuses: [400, 401], + empty: false, + }, + requestOptions, + ), + attemptStatus: (input: IntegrationsAttemptStatusInput, requestOptions?: RequestOptions) => + request( + { + method: "GET", + path: `/api/integration/attempt/${encodeURIComponent(input.attemptID)}`, + query: { location: input["location"] }, + successStatus: 200, + declaredStatuses: [401, 400], + empty: false, + }, + requestOptions, + ), + attemptComplete: (input: IntegrationsAttemptCompleteInput, requestOptions?: RequestOptions) => + request( + { + method: "POST", + path: `/api/integration/attempt/${encodeURIComponent(input.attemptID)}/complete`, + query: { location: input["location"] }, + body: { code: input["code"] }, + successStatus: 204, + declaredStatuses: [400, 401], + empty: true, + }, + requestOptions, + ), + attemptCancel: (input: IntegrationsAttemptCancelInput, requestOptions?: RequestOptions) => + request( + { + method: "DELETE", + path: `/api/integration/attempt/${encodeURIComponent(input.attemptID)}`, + query: { location: input["location"] }, + successStatus: 204, + declaredStatuses: [401, 400], + empty: true, + }, + requestOptions, + ), + }, + credentials: { + update: (input: CredentialsUpdateInput, requestOptions?: RequestOptions) => + request( + { + method: "PATCH", + path: `/api/credential/${encodeURIComponent(input.credentialID)}`, + query: { location: input["location"] }, + body: { label: input["label"] }, + successStatus: 204, + declaredStatuses: [401, 400], + empty: true, + }, + requestOptions, + ), + remove: (input: CredentialsRemoveInput, requestOptions?: RequestOptions) => + request( + { + method: "DELETE", + path: `/api/credential/${encodeURIComponent(input.credentialID)}`, + query: { location: input["location"] }, + successStatus: 204, + declaredStatuses: [401, 400], + empty: true, + }, + requestOptions, + ), + }, + permissions: { + listRequests: (input?: PermissionsListRequestsInput, requestOptions?: RequestOptions) => + request( + { + method: "GET", + path: `/api/permission/request`, + query: { location: input?.["location"] }, + successStatus: 200, + declaredStatuses: [401, 400], + empty: false, + }, + requestOptions, + ), + listSaved: (input?: PermissionsListSavedInput, requestOptions?: RequestOptions) => + request<{ readonly data: PermissionsListSavedOutput }>( + { + method: "GET", + path: `/api/permission/saved`, + query: { projectID: input?.["projectID"] }, + successStatus: 200, + declaredStatuses: [401, 400], + empty: false, + }, + requestOptions, + ).then((value) => value.data), + removeSaved: (input: PermissionsRemoveSavedInput, requestOptions?: RequestOptions) => + request( + { + method: "DELETE", + path: `/api/permission/saved/${encodeURIComponent(input.id)}`, + successStatus: 204, + declaredStatuses: [401, 400], + empty: true, + }, + requestOptions, + ), + create: (input: PermissionsCreateInput, requestOptions?: RequestOptions) => + request<{ readonly data: PermissionsCreateOutput }>( + { + method: "POST", + path: `/api/session/${encodeURIComponent(input.sessionID)}/permission`, + body: { + id: input["id"], + action: input["action"], + resources: input["resources"], + save: input["save"], + metadata: input["metadata"], + source: input["source"], + agent: input["agent"], + }, + successStatus: 200, + declaredStatuses: [404, 400, 401], + empty: false, + }, + requestOptions, + ).then((value) => value.data), + list: (input: PermissionsListInput, requestOptions?: RequestOptions) => + request<{ readonly data: PermissionsListOutput }>( + { + method: "GET", + path: `/api/session/${encodeURIComponent(input.sessionID)}/permission`, + successStatus: 200, + declaredStatuses: [404, 400, 401], + empty: false, + }, + requestOptions, + ).then((value) => value.data), + get: (input: PermissionsGetInput, requestOptions?: RequestOptions) => + request<{ readonly data: PermissionsGetOutput }>( + { + method: "GET", + path: `/api/session/${encodeURIComponent(input.sessionID)}/permission/${encodeURIComponent(input.requestID)}`, + successStatus: 200, + declaredStatuses: [404, 400, 401], + empty: false, + }, + requestOptions, + ).then((value) => value.data), + reply: (input: PermissionsReplyInput, requestOptions?: RequestOptions) => + request( + { + method: "POST", + path: `/api/session/${encodeURIComponent(input.sessionID)}/permission/${encodeURIComponent(input.requestID)}/reply`, + body: { reply: input["reply"], message: input["message"] }, + successStatus: 204, + declaredStatuses: [404, 400, 401], + empty: true, + }, + requestOptions, + ), + }, + files: { + list: (input?: FilesListInput, requestOptions?: RequestOptions) => + request( + { + method: "GET", + path: `/api/fs/list`, + query: { location: input?.["location"], path: input?.["path"] }, + successStatus: 200, + declaredStatuses: [401, 400], + empty: false, + }, + requestOptions, + ), + find: (input: FilesFindInput, requestOptions?: RequestOptions) => + request( + { + method: "GET", + path: `/api/fs/find`, + query: { location: input["location"], query: input["query"], type: input["type"], limit: input["limit"] }, + successStatus: 200, + declaredStatuses: [401, 400], + empty: false, + }, + requestOptions, + ), + }, + commands: { + list: (input?: CommandsListInput, requestOptions?: RequestOptions) => + request( + { + method: "GET", + path: `/api/command`, + query: { location: input?.["location"] }, + successStatus: 200, + declaredStatuses: [401, 400], + empty: false, + }, + requestOptions, + ), + }, + skills: { + list: (input?: SkillsListInput, requestOptions?: RequestOptions) => + request( + { + method: "GET", + path: `/api/skill`, + query: { location: input?.["location"] }, + successStatus: 200, + declaredStatuses: [401, 400], + empty: false, + }, + requestOptions, + ), + }, events: { subscribe: (requestOptions?: RequestOptions): AsyncIterable => sse( @@ -381,6 +815,178 @@ export function make(options: ClientOptions) { requestOptions, ), }, + ptys: { + list: (input?: PtysListInput, requestOptions?: RequestOptions) => + request( + { + method: "GET", + path: `/api/pty`, + query: { location: input?.["location"] }, + successStatus: 200, + declaredStatuses: [401, 400], + empty: false, + }, + requestOptions, + ), + create: (input?: PtysCreateInput, requestOptions?: RequestOptions) => + request( + { + method: "POST", + path: `/api/pty`, + query: { location: input?.["location"] }, + body: { + command: input?.["command"], + args: input?.["args"], + cwd: input?.["cwd"], + title: input?.["title"], + env: input?.["env"], + }, + successStatus: 200, + declaredStatuses: [401, 400], + empty: false, + }, + requestOptions, + ), + get: (input: PtysGetInput, requestOptions?: RequestOptions) => + request( + { + method: "GET", + path: `/api/pty/${encodeURIComponent(input.ptyID)}`, + query: { location: input["location"] }, + successStatus: 200, + declaredStatuses: [404, 401, 400], + empty: false, + }, + requestOptions, + ), + update: (input: PtysUpdateInput, requestOptions?: RequestOptions) => + request( + { + method: "PUT", + path: `/api/pty/${encodeURIComponent(input.ptyID)}`, + query: { location: input["location"] }, + body: { title: input["title"], size: input["size"] }, + successStatus: 200, + declaredStatuses: [404, 401, 400], + empty: false, + }, + requestOptions, + ), + remove: (input: PtysRemoveInput, requestOptions?: RequestOptions) => + request( + { + method: "DELETE", + path: `/api/pty/${encodeURIComponent(input.ptyID)}`, + query: { location: input["location"] }, + successStatus: 204, + declaredStatuses: [404, 401, 400], + empty: true, + }, + requestOptions, + ), + }, + questions: { + listRequests: (input?: QuestionsListRequestsInput, requestOptions?: RequestOptions) => + request( + { + method: "GET", + path: `/api/question/request`, + query: { location: input?.["location"] }, + successStatus: 200, + declaredStatuses: [401, 400], + empty: false, + }, + requestOptions, + ), + list: (input: QuestionsListInput, requestOptions?: RequestOptions) => + request<{ readonly data: QuestionsListOutput }>( + { + method: "GET", + path: `/api/session/${encodeURIComponent(input.sessionID)}/question`, + successStatus: 200, + declaredStatuses: [404, 400, 401], + empty: false, + }, + requestOptions, + ).then((value) => value.data), + reply: (input: QuestionsReplyInput, requestOptions?: RequestOptions) => + request( + { + method: "POST", + path: `/api/session/${encodeURIComponent(input.sessionID)}/question/${encodeURIComponent(input.requestID)}/reply`, + body: { answers: input["answers"] }, + successStatus: 204, + declaredStatuses: [404, 400, 401], + empty: true, + }, + requestOptions, + ), + reject: (input: QuestionsRejectInput, requestOptions?: RequestOptions) => + request( + { + method: "POST", + path: `/api/session/${encodeURIComponent(input.sessionID)}/question/${encodeURIComponent(input.requestID)}/reject`, + successStatus: 204, + declaredStatuses: [404, 400, 401], + empty: true, + }, + requestOptions, + ), + }, + references: { + list: (input?: ReferencesListInput, requestOptions?: RequestOptions) => + request( + { + method: "GET", + path: `/api/reference`, + query: { location: input?.["location"] }, + successStatus: 200, + declaredStatuses: [401, 400], + empty: false, + }, + requestOptions, + ), + }, + projectCopies: { + create: (input: ProjectCopiesCreateInput, requestOptions?: RequestOptions) => + request( + { + method: "POST", + path: `/experimental/project/${encodeURIComponent(input.projectID)}/copy`, + query: { location: input["location"] }, + body: { strategy: input["strategy"], directory: input["directory"], name: input["name"] }, + successStatus: 200, + declaredStatuses: [400, 401], + empty: false, + }, + requestOptions, + ), + remove: (input: ProjectCopiesRemoveInput, requestOptions?: RequestOptions) => + request( + { + method: "DELETE", + path: `/experimental/project/${encodeURIComponent(input.projectID)}/copy`, + query: { location: input["location"] }, + body: { directory: input["directory"], force: input["force"] }, + successStatus: 204, + declaredStatuses: [400, 401], + empty: true, + }, + requestOptions, + ), + refresh: (input: ProjectCopiesRefreshInput, requestOptions?: RequestOptions) => + request( + { + method: "POST", + path: `/experimental/project/${encodeURIComponent(input.projectID)}/copy/refresh`, + query: { location: input["location"] }, + successStatus: 204, + declaredStatuses: [400, 401], + empty: true, + }, + requestOptions, + ), + }, } } diff --git a/packages/client/src/generated/types.ts b/packages/client/src/generated/types.ts index 88f1f89b31d0..3b3188c8742a 100644 --- a/packages/client/src/generated/types.ts +++ b/packages/client/src/generated/types.ts @@ -8,9 +8,9 @@ export type JsonValue = | ReadonlyArray | { readonly [key: string]: JsonValue } -export type InvalidCursorError = { readonly _tag: "InvalidCursorError"; readonly message: string } -export const isInvalidCursorError = (value: unknown): value is InvalidCursorError => - typeof value === "object" && value !== null && "_tag" in value && value._tag === "InvalidCursorError" +export type UnauthorizedError = { readonly _tag: "UnauthorizedError"; readonly message: string } +export const isUnauthorizedError = (value: unknown): value is UnauthorizedError => + typeof value === "object" && value !== null && "_tag" in value && value["_tag"] === "UnauthorizedError" export type InvalidRequestError = { readonly _tag: "InvalidRequestError" @@ -19,11 +19,11 @@ export type InvalidRequestError = { readonly field?: string | undefined } export const isInvalidRequestError = (value: unknown): value is InvalidRequestError => - typeof value === "object" && value !== null && "_tag" in value && value._tag === "InvalidRequestError" + typeof value === "object" && value !== null && "_tag" in value && value["_tag"] === "InvalidRequestError" -export type UnauthorizedError = { readonly _tag: "UnauthorizedError"; readonly message: string } -export const isUnauthorizedError = (value: unknown): value is UnauthorizedError => - typeof value === "object" && value !== null && "_tag" in value && value._tag === "UnauthorizedError" +export type InvalidCursorError = { readonly _tag: "InvalidCursorError"; readonly message: string } +export const isInvalidCursorError = (value: unknown): value is InvalidCursorError => + typeof value === "object" && value !== null && "_tag" in value && value["_tag"] === "InvalidCursorError" export type SessionNotFoundError = { readonly _tag: "SessionNotFoundError" @@ -31,7 +31,7 @@ export type SessionNotFoundError = { readonly message: string } export const isSessionNotFoundError = (value: unknown): value is SessionNotFoundError => - typeof value === "object" && value !== null && "_tag" in value && value._tag === "SessionNotFoundError" + typeof value === "object" && value !== null && "_tag" in value && value["_tag"] === "SessionNotFoundError" export type ConflictError = { readonly _tag: "ConflictError" @@ -39,7 +39,7 @@ export type ConflictError = { readonly resource?: string | undefined } export const isConflictError = (value: unknown): value is ConflictError => - typeof value === "object" && value !== null && "_tag" in value && value._tag === "ConflictError" + typeof value === "object" && value !== null && "_tag" in value && value["_tag"] === "ConflictError" export type ServiceUnavailableError = { readonly _tag: "ServiceUnavailableError" @@ -47,7 +47,7 @@ export type ServiceUnavailableError = { readonly service?: string | undefined } export const isServiceUnavailableError = (value: unknown): value is ServiceUnavailableError => - typeof value === "object" && value !== null && "_tag" in value && value._tag === "ServiceUnavailableError" + typeof value === "object" && value !== null && "_tag" in value && value["_tag"] === "ServiceUnavailableError" export type MessageNotFoundError = { readonly _tag: "MessageNotFoundError" @@ -56,7 +56,7 @@ export type MessageNotFoundError = { readonly message: string } export const isMessageNotFoundError = (value: unknown): value is MessageNotFoundError => - typeof value === "object" && value !== null && "_tag" in value && value._tag === "MessageNotFoundError" + typeof value === "object" && value !== null && "_tag" in value && value["_tag"] === "MessageNotFoundError" export type UnknownError = { readonly _tag: "UnknownError" @@ -64,7 +64,89 @@ export type UnknownError = { readonly ref?: string | undefined } export const isUnknownError = (value: unknown): value is UnknownError => - typeof value === "object" && value !== null && "_tag" in value && value._tag === "UnknownError" + typeof value === "object" && value !== null && "_tag" in value && value["_tag"] === "UnknownError" + +export type ProviderNotFoundError = { + readonly _tag: "ProviderNotFoundError" + readonly providerID: string + readonly message: string +} +export const isProviderNotFoundError = (value: unknown): value is ProviderNotFoundError => + typeof value === "object" && value !== null && "_tag" in value && value["_tag"] === "ProviderNotFoundError" + +export type PermissionNotFoundError = { + readonly _tag: "PermissionNotFoundError" + readonly requestID: string + readonly message: string +} +export const isPermissionNotFoundError = (value: unknown): value is PermissionNotFoundError => + typeof value === "object" && value !== null && "_tag" in value && value["_tag"] === "PermissionNotFoundError" + +export type PtyNotFoundError = { readonly _tag: "PtyNotFoundError"; readonly ptyID: string; readonly message: string } +export const isPtyNotFoundError = (value: unknown): value is PtyNotFoundError => + typeof value === "object" && value !== null && "_tag" in value && value["_tag"] === "PtyNotFoundError" + +export type QuestionNotFoundError = { + readonly _tag: "QuestionNotFoundError" + readonly requestID: string + readonly message: string +} +export const isQuestionNotFoundError = (value: unknown): value is QuestionNotFoundError => + typeof value === "object" && value !== null && "_tag" in value && value["_tag"] === "QuestionNotFoundError" + +export type ProjectCopyError = { + readonly name: "ProjectCopyError" + readonly data: { readonly message: string; readonly forceRequired?: boolean | undefined } +} +export const isProjectCopyError = (value: unknown): value is ProjectCopyError => + typeof value === "object" && value !== null && "name" in value && value["name"] === "ProjectCopyError" + +export type HealthGetOutput = { readonly healthy: true } + +export type LocationGetInput = { + readonly location?: { + readonly location?: { readonly directory?: string | undefined; readonly workspace?: string | undefined } | undefined + }["location"] +} + +export type LocationGetOutput = { + readonly directory: string + readonly workspaceID?: string + readonly project: { readonly id: string; readonly directory: string } +} + +export type AgentsListInput = { + readonly location?: { + readonly location?: { readonly directory?: string | undefined; readonly workspace?: string | undefined } | undefined + }["location"] +} + +export type AgentsListOutput = { + readonly location: { + readonly directory: string + readonly workspaceID?: string + readonly project: { readonly id: string; readonly directory: string } + } + readonly data: ReadonlyArray<{ + readonly id: string + readonly model?: { readonly id: string; readonly providerID: string; readonly variant?: string } + readonly request: { + readonly headers: { readonly [x: string]: string } + readonly body: { readonly [x: string]: JsonValue } + } + readonly system?: string + readonly description?: string + readonly mode: "subagent" | "primary" | "all" + readonly hidden: boolean + readonly color?: string | "primary" | "secondary" | "accent" | "success" | "warning" | "error" | "info" + readonly steps?: number + readonly permissions: ReadonlyArray<{ + readonly action: string + readonly resource: string + readonly effect: "allow" | "deny" | "ask" + }> + }> +} export type SessionsListInput = { readonly workspace?: { @@ -1671,4 +1753,1055 @@ export type SessionsMessageOutput = { } }["data"] -export type EventsSubscribeOutput = OpenCodeEventEncoded +export type MessagesListInput = { + readonly sessionID: { readonly sessionID: string }["sessionID"] + readonly limit?: { + readonly limit?: number | undefined + readonly order?: "asc" | "desc" | undefined + readonly cursor?: string | undefined + }["limit"] + readonly order?: { + readonly limit?: number | undefined + readonly order?: "asc" | "desc" | undefined + readonly cursor?: string | undefined + }["order"] + readonly cursor?: { + readonly limit?: number | undefined + readonly order?: "asc" | "desc" | undefined + readonly cursor?: string | undefined + }["cursor"] +} + +export type MessagesListOutput = { + readonly data: ReadonlyArray< + | { + readonly id: string + readonly metadata?: { readonly [x: string]: JsonValue } + readonly time: { readonly created: number } + readonly type: "agent-switched" + readonly agent: string + } + | { + readonly id: string + readonly metadata?: { readonly [x: string]: JsonValue } + readonly time: { readonly created: number } + readonly type: "model-switched" + readonly model: { readonly id: string; readonly providerID: string; readonly variant?: string } + } + | { + readonly id: string + readonly metadata?: { readonly [x: string]: JsonValue } + readonly time: { readonly created: number } + readonly text: string + readonly files?: ReadonlyArray<{ + readonly uri: string + readonly mime: string + readonly name?: string + readonly description?: string + readonly source?: { readonly start: number; readonly end: number; readonly text: string } + }> + readonly agents?: ReadonlyArray<{ + readonly name: string + readonly source?: { readonly start: number; readonly end: number; readonly text: string } + }> + readonly type: "user" + } + | { + readonly id: string + readonly metadata?: { readonly [x: string]: JsonValue } + readonly time: { readonly created: number } + readonly sessionID: string + readonly text: string + readonly type: "synthetic" + } + | { + readonly id: string + readonly metadata?: { readonly [x: string]: JsonValue } + readonly time: { readonly created: number } + readonly type: "system" + readonly text: string + } + | { + readonly id: string + readonly metadata?: { readonly [x: string]: JsonValue } + readonly time: { readonly created: number; readonly completed?: number } + readonly type: "shell" + readonly callID: string + readonly command: string + readonly output: string + } + | { + readonly id: string + readonly metadata?: { readonly [x: string]: JsonValue } + readonly time: { readonly created: number; readonly completed?: number } + readonly type: "assistant" + readonly agent: string + readonly model: { readonly id: string; readonly providerID: string; readonly variant?: string } + readonly content: ReadonlyArray< + | { readonly type: "text"; readonly id: string; readonly text: string } + | { + readonly type: "reasoning" + readonly id: string + readonly text: string + readonly providerMetadata?: { readonly [x: string]: { readonly [x: string]: JsonValue } } + readonly time?: { readonly created: number; readonly completed?: number } + } + | { + readonly type: "tool" + readonly id: string + readonly name: string + readonly provider?: { + readonly executed: boolean + readonly metadata?: { readonly [x: string]: { readonly [x: string]: JsonValue } } + readonly resultMetadata?: { readonly [x: string]: { readonly [x: string]: JsonValue } } + } + readonly state: + | { readonly status: "pending"; readonly input: string } + | { + readonly status: "running" + readonly input: { readonly [x: string]: JsonValue } + readonly structured: { readonly [x: string]: JsonValue } + readonly content: ReadonlyArray< + | { readonly type: "text"; readonly text: string } + | { readonly type: "file"; readonly uri: string; readonly mime: string; readonly name?: string } + > + } + | { + readonly status: "completed" + readonly input: { readonly [x: string]: JsonValue } + readonly attachments?: ReadonlyArray<{ + readonly uri: string + readonly mime: string + readonly name?: string + readonly description?: string + readonly source?: { readonly start: number; readonly end: number; readonly text: string } + }> + readonly content: ReadonlyArray< + | { readonly type: "text"; readonly text: string } + | { readonly type: "file"; readonly uri: string; readonly mime: string; readonly name?: string } + > + readonly outputPaths?: ReadonlyArray + readonly structured: { readonly [x: string]: JsonValue } + readonly result?: JsonValue + } + | { + readonly status: "error" + readonly input: { readonly [x: string]: JsonValue } + readonly content: ReadonlyArray< + | { readonly type: "text"; readonly text: string } + | { readonly type: "file"; readonly uri: string; readonly mime: string; readonly name?: string } + > + readonly structured: { readonly [x: string]: JsonValue } + readonly error: { readonly type: "unknown"; readonly message: string } + readonly result?: JsonValue + } + readonly time: { + readonly created: number + readonly ran?: number + readonly completed?: number + readonly pruned?: number + } + } + > + readonly snapshot?: { readonly start?: string; readonly end?: string; readonly files?: ReadonlyArray } + readonly finish?: string + readonly cost?: number + readonly tokens?: { + readonly input: number + readonly output: number + readonly reasoning: number + readonly cache: { readonly read: number; readonly write: number } + } + readonly error?: { readonly type: "unknown"; readonly message: string } + } + | { + readonly type: "compaction" + readonly reason: "auto" | "manual" + readonly summary: string + readonly recent: string + readonly id: string + readonly metadata?: { readonly [x: string]: JsonValue } + readonly time: { readonly created: number } + } + > + readonly cursor: { readonly previous?: string | null; readonly next?: string | null } +} + +export type ModelsListInput = { + readonly location?: { + readonly location?: { readonly directory?: string | undefined; readonly workspace?: string | undefined } | undefined + }["location"] +} + +export type ModelsListOutput = { + readonly location: { + readonly directory: string + readonly workspaceID?: string + readonly project: { readonly id: string; readonly directory: string } + } + readonly data: ReadonlyArray<{ + readonly id: string + readonly providerID: string + readonly family?: string + readonly name: string + readonly api: + | { + readonly id: string + readonly type: "aisdk" + readonly package: string + readonly url?: string + readonly settings?: { readonly [x: string]: JsonValue } + } + | { + readonly id: string + readonly type: "native" + readonly url?: string + readonly settings: { readonly [x: string]: JsonValue } + } + readonly capabilities: { + readonly tools: boolean + readonly input: ReadonlyArray + readonly output: ReadonlyArray + } + readonly request: { + readonly headers: { readonly [x: string]: string } + readonly body: { readonly [x: string]: JsonValue } + readonly variant?: string + } + readonly variants: ReadonlyArray<{ + readonly id: string + readonly headers: { readonly [x: string]: string } + readonly body: { readonly [x: string]: JsonValue } + }> + readonly time: { readonly released: number } + readonly cost: ReadonlyArray<{ + readonly tier?: { readonly type: "context"; readonly size: number } + readonly input: number + readonly output: number + readonly cache: { readonly read: number; readonly write: number } + }> + readonly status: "alpha" | "beta" | "deprecated" | "active" + readonly enabled: boolean + readonly limit: { readonly context: number; readonly input?: number; readonly output: number } + }> +} + +export type ProvidersListInput = { + readonly location?: { + readonly location?: { readonly directory?: string | undefined; readonly workspace?: string | undefined } | undefined + }["location"] +} + +export type ProvidersListOutput = { + readonly location: { + readonly directory: string + readonly workspaceID?: string + readonly project: { readonly id: string; readonly directory: string } + } + readonly data: ReadonlyArray<{ + readonly id: string + readonly integrationID?: string + readonly name: string + readonly disabled?: boolean + readonly api: + | { + readonly type: "aisdk" + readonly package: string + readonly url?: string + readonly settings?: { readonly [x: string]: JsonValue } + } + | { readonly type: "native"; readonly url?: string; readonly settings: { readonly [x: string]: JsonValue } } + readonly request: { + readonly headers: { readonly [x: string]: string } + readonly body: { readonly [x: string]: JsonValue } + } + }> +} + +export type ProvidersGetInput = { + readonly providerID: { readonly providerID: string }["providerID"] + readonly location?: { + readonly location?: { readonly directory?: string | undefined; readonly workspace?: string | undefined } | undefined + }["location"] +} + +export type ProvidersGetOutput = { + readonly location: { + readonly directory: string + readonly workspaceID?: string + readonly project: { readonly id: string; readonly directory: string } + } + readonly data: { + readonly id: string + readonly integrationID?: string + readonly name: string + readonly disabled?: boolean + readonly api: + | { + readonly type: "aisdk" + readonly package: string + readonly url?: string + readonly settings?: { readonly [x: string]: JsonValue } + } + | { readonly type: "native"; readonly url?: string; readonly settings: { readonly [x: string]: JsonValue } } + readonly request: { + readonly headers: { readonly [x: string]: string } + readonly body: { readonly [x: string]: JsonValue } + } + } +} + +export type IntegrationsListInput = { + readonly location?: { + readonly location?: { readonly directory?: string | undefined; readonly workspace?: string | undefined } | undefined + }["location"] +} + +export type IntegrationsListOutput = { + readonly location: { + readonly directory: string + readonly workspaceID?: string + readonly project: { readonly id: string; readonly directory: string } + } + readonly data: ReadonlyArray<{ + readonly id: string + readonly name: string + readonly methods: ReadonlyArray< + | { + readonly id: string + readonly type: "oauth" + readonly label: string + readonly prompts?: ReadonlyArray< + | { + readonly type: "text" + readonly key: string + readonly message: string + readonly placeholder?: string + readonly when?: { readonly key: string; readonly op: "eq" | "neq"; readonly value: string } + } + | { + readonly type: "select" + readonly key: string + readonly message: string + readonly options: ReadonlyArray<{ + readonly label: string + readonly value: string + readonly hint?: string + }> + readonly when?: { readonly key: string; readonly op: "eq" | "neq"; readonly value: string } + } + > + } + | { readonly type: "key"; readonly label?: string } + | { readonly type: "env"; readonly names: ReadonlyArray } + > + readonly connections: ReadonlyArray< + | { readonly type: "credential"; readonly id: string; readonly label: string } + | { readonly type: "env"; readonly name: string } + > + }> +} + +export type IntegrationsGetInput = { + readonly integrationID: { readonly integrationID: string }["integrationID"] + readonly location?: { + readonly location?: { readonly directory?: string | undefined; readonly workspace?: string | undefined } | undefined + }["location"] +} + +export type IntegrationsGetOutput = { + readonly location: { + readonly directory: string + readonly workspaceID?: string + readonly project: { readonly id: string; readonly directory: string } + } + readonly data: { + readonly id: string + readonly name: string + readonly methods: ReadonlyArray< + | { + readonly id: string + readonly type: "oauth" + readonly label: string + readonly prompts?: ReadonlyArray< + | { + readonly type: "text" + readonly key: string + readonly message: string + readonly placeholder?: string + readonly when?: { readonly key: string; readonly op: "eq" | "neq"; readonly value: string } + } + | { + readonly type: "select" + readonly key: string + readonly message: string + readonly options: ReadonlyArray<{ + readonly label: string + readonly value: string + readonly hint?: string + }> + readonly when?: { readonly key: string; readonly op: "eq" | "neq"; readonly value: string } + } + > + } + | { readonly type: "key"; readonly label?: string } + | { readonly type: "env"; readonly names: ReadonlyArray } + > + readonly connections: ReadonlyArray< + | { readonly type: "credential"; readonly id: string; readonly label: string } + | { readonly type: "env"; readonly name: string } + > + } | null +} + +export type IntegrationsConnectKeyInput = { + readonly integrationID: { readonly integrationID: string }["integrationID"] + readonly location?: { + readonly location?: { readonly directory?: string | undefined; readonly workspace?: string | undefined } | undefined + }["location"] + readonly key: { readonly key: string; readonly label?: string | undefined }["key"] + readonly label?: { readonly key: string; readonly label?: string | undefined }["label"] +} + +export type IntegrationsConnectKeyOutput = void + +export type IntegrationsConnectOauthInput = { + readonly integrationID: { readonly integrationID: string }["integrationID"] + readonly location?: { + readonly location?: { readonly directory?: string | undefined; readonly workspace?: string | undefined } | undefined + }["location"] + readonly methodID: { + readonly methodID: string + readonly inputs: { readonly [x: string]: string } + readonly label?: string | undefined + }["methodID"] + readonly inputs: { + readonly methodID: string + readonly inputs: { readonly [x: string]: string } + readonly label?: string | undefined + }["inputs"] + readonly label?: { + readonly methodID: string + readonly inputs: { readonly [x: string]: string } + readonly label?: string | undefined + }["label"] +} + +export type IntegrationsConnectOauthOutput = { + readonly location: { + readonly directory: string + readonly workspaceID?: string + readonly project: { readonly id: string; readonly directory: string } + } + readonly data: { + readonly attemptID: string + readonly url: string + readonly instructions: string + readonly mode: "auto" | "code" + readonly time: { + readonly created: number | "Infinity" | "-Infinity" | "NaN" + readonly expires: number | "Infinity" | "-Infinity" | "NaN" + } + } +} + +export type IntegrationsAttemptStatusInput = { + readonly attemptID: { readonly attemptID: string }["attemptID"] + readonly location?: { + readonly location?: { readonly directory?: string | undefined; readonly workspace?: string | undefined } | undefined + }["location"] +} + +export type IntegrationsAttemptStatusOutput = { + readonly location: { + readonly directory: string + readonly workspaceID?: string + readonly project: { readonly id: string; readonly directory: string } + } + readonly data: + | { + readonly status: "pending" + readonly time: { + readonly created: number | "Infinity" | "-Infinity" | "NaN" + readonly expires: number | "Infinity" | "-Infinity" | "NaN" + } + } + | { + readonly status: "complete" + readonly time: { + readonly created: number | "Infinity" | "-Infinity" | "NaN" + readonly expires: number | "Infinity" | "-Infinity" | "NaN" + } + } + | { + readonly status: "failed" + readonly message: string + readonly time: { + readonly created: number | "Infinity" | "-Infinity" | "NaN" + readonly expires: number | "Infinity" | "-Infinity" | "NaN" + } + } + | { + readonly status: "expired" + readonly time: { + readonly created: number | "Infinity" | "-Infinity" | "NaN" + readonly expires: number | "Infinity" | "-Infinity" | "NaN" + } + } +} + +export type IntegrationsAttemptCompleteInput = { + readonly attemptID: { readonly attemptID: string }["attemptID"] + readonly location?: { + readonly location?: { readonly directory?: string | undefined; readonly workspace?: string | undefined } | undefined + }["location"] + readonly code?: { readonly code?: string | undefined }["code"] +} + +export type IntegrationsAttemptCompleteOutput = void + +export type IntegrationsAttemptCancelInput = { + readonly attemptID: { readonly attemptID: string }["attemptID"] + readonly location?: { + readonly location?: { readonly directory?: string | undefined; readonly workspace?: string | undefined } | undefined + }["location"] +} + +export type IntegrationsAttemptCancelOutput = void + +export type CredentialsUpdateInput = { + readonly credentialID: { readonly credentialID: string }["credentialID"] + readonly location?: { + readonly location?: { readonly directory?: string | undefined; readonly workspace?: string | undefined } | undefined + }["location"] + readonly label: { readonly label: string }["label"] +} + +export type CredentialsUpdateOutput = void + +export type CredentialsRemoveInput = { + readonly credentialID: { readonly credentialID: string }["credentialID"] + readonly location?: { + readonly location?: { readonly directory?: string | undefined; readonly workspace?: string | undefined } | undefined + }["location"] +} + +export type CredentialsRemoveOutput = void + +export type PermissionsListRequestsInput = { + readonly location?: { + readonly location?: { readonly directory?: string | undefined; readonly workspace?: string | undefined } | undefined + }["location"] +} + +export type PermissionsListRequestsOutput = { + readonly location: { + readonly directory: string + readonly workspaceID?: string + readonly project: { readonly id: string; readonly directory: string } + } + readonly data: ReadonlyArray<{ + readonly id: string + readonly sessionID: string + readonly action: string + readonly resources: ReadonlyArray + readonly save?: ReadonlyArray + readonly metadata?: { readonly [x: string]: JsonValue } + readonly source?: { readonly type: "tool"; readonly messageID: string; readonly callID: string } + }> +} + +export type PermissionsListSavedInput = { + readonly projectID?: { readonly projectID?: string | undefined }["projectID"] +} + +export type PermissionsListSavedOutput = { + readonly data: ReadonlyArray<{ + readonly id: string + readonly projectID: string + readonly action: string + readonly resource: string + }> +}["data"] + +export type PermissionsRemoveSavedInput = { readonly id: { readonly id: string }["id"] } + +export type PermissionsRemoveSavedOutput = void + +export type PermissionsCreateInput = { + readonly sessionID: { readonly sessionID: string }["sessionID"] + readonly id?: { + readonly id?: string | null + readonly action: string + readonly resources: ReadonlyArray + readonly save?: ReadonlyArray + readonly metadata?: { readonly [x: string]: JsonValue } + readonly source?: { readonly type: "tool"; readonly messageID: string; readonly callID: string } + readonly agent?: string | null + }["id"] + readonly action: { + readonly id?: string | null + readonly action: string + readonly resources: ReadonlyArray + readonly save?: ReadonlyArray + readonly metadata?: { readonly [x: string]: JsonValue } + readonly source?: { readonly type: "tool"; readonly messageID: string; readonly callID: string } + readonly agent?: string | null + }["action"] + readonly resources: { + readonly id?: string | null + readonly action: string + readonly resources: ReadonlyArray + readonly save?: ReadonlyArray + readonly metadata?: { readonly [x: string]: JsonValue } + readonly source?: { readonly type: "tool"; readonly messageID: string; readonly callID: string } + readonly agent?: string | null + }["resources"] + readonly save?: { + readonly id?: string | null + readonly action: string + readonly resources: ReadonlyArray + readonly save?: ReadonlyArray + readonly metadata?: { readonly [x: string]: JsonValue } + readonly source?: { readonly type: "tool"; readonly messageID: string; readonly callID: string } + readonly agent?: string | null + }["save"] + readonly metadata?: { + readonly id?: string | null + readonly action: string + readonly resources: ReadonlyArray + readonly save?: ReadonlyArray + readonly metadata?: { readonly [x: string]: JsonValue } + readonly source?: { readonly type: "tool"; readonly messageID: string; readonly callID: string } + readonly agent?: string | null + }["metadata"] + readonly source?: { + readonly id?: string | null + readonly action: string + readonly resources: ReadonlyArray + readonly save?: ReadonlyArray + readonly metadata?: { readonly [x: string]: JsonValue } + readonly source?: { readonly type: "tool"; readonly messageID: string; readonly callID: string } + readonly agent?: string | null + }["source"] + readonly agent?: { + readonly id?: string | null + readonly action: string + readonly resources: ReadonlyArray + readonly save?: ReadonlyArray + readonly metadata?: { readonly [x: string]: JsonValue } + readonly source?: { readonly type: "tool"; readonly messageID: string; readonly callID: string } + readonly agent?: string | null + }["agent"] +} + +export type PermissionsCreateOutput = { + readonly data: { readonly id: string; readonly effect: "allow" | "deny" | "ask" } +}["data"] + +export type PermissionsListInput = { readonly sessionID: { readonly sessionID: string }["sessionID"] } + +export type PermissionsListOutput = { + readonly data: ReadonlyArray<{ + readonly id: string + readonly sessionID: string + readonly action: string + readonly resources: ReadonlyArray + readonly save?: ReadonlyArray + readonly metadata?: { readonly [x: string]: JsonValue } + readonly source?: { readonly type: "tool"; readonly messageID: string; readonly callID: string } + }> +}["data"] + +export type PermissionsGetInput = { + readonly sessionID: { readonly sessionID: string; readonly requestID: string }["sessionID"] + readonly requestID: { readonly sessionID: string; readonly requestID: string }["requestID"] +} + +export type PermissionsGetOutput = { + readonly data: { + readonly id: string + readonly sessionID: string + readonly action: string + readonly resources: ReadonlyArray + readonly save?: ReadonlyArray + readonly metadata?: { readonly [x: string]: JsonValue } + readonly source?: { readonly type: "tool"; readonly messageID: string; readonly callID: string } + } +}["data"] + +export type PermissionsReplyInput = { + readonly sessionID: { readonly sessionID: string; readonly requestID: string }["sessionID"] + readonly requestID: { readonly sessionID: string; readonly requestID: string }["requestID"] + readonly reply: { readonly reply: "once" | "always" | "reject"; readonly message?: string | undefined }["reply"] + readonly message?: { readonly reply: "once" | "always" | "reject"; readonly message?: string | undefined }["message"] +} + +export type PermissionsReplyOutput = void + +export type FilesListInput = { + readonly location?: { + readonly location?: { readonly directory?: string | undefined; readonly workspace?: string | undefined } | undefined + readonly path?: string | undefined + }["location"] + readonly path?: { + readonly location?: { readonly directory?: string | undefined; readonly workspace?: string | undefined } | undefined + readonly path?: string | undefined + }["path"] +} + +export type FilesListOutput = { + readonly location: { + readonly directory: string + readonly workspaceID?: string + readonly project: { readonly id: string; readonly directory: string } + } + readonly data: ReadonlyArray<{ readonly path: string; readonly type: "file" | "directory" }> +} + +export type FilesFindInput = { + readonly location?: { + readonly location?: { readonly directory?: string | undefined; readonly workspace?: string | undefined } | undefined + readonly query: string + readonly type?: "file" | "directory" | undefined + readonly limit?: number | undefined + }["location"] + readonly query: { + readonly location?: { readonly directory?: string | undefined; readonly workspace?: string | undefined } | undefined + readonly query: string + readonly type?: "file" | "directory" | undefined + readonly limit?: number | undefined + }["query"] + readonly type?: { + readonly location?: { readonly directory?: string | undefined; readonly workspace?: string | undefined } | undefined + readonly query: string + readonly type?: "file" | "directory" | undefined + readonly limit?: number | undefined + }["type"] + readonly limit?: { + readonly location?: { readonly directory?: string | undefined; readonly workspace?: string | undefined } | undefined + readonly query: string + readonly type?: "file" | "directory" | undefined + readonly limit?: number | undefined + }["limit"] +} + +export type FilesFindOutput = { + readonly location: { + readonly directory: string + readonly workspaceID?: string + readonly project: { readonly id: string; readonly directory: string } + } + readonly data: ReadonlyArray<{ readonly path: string; readonly type: "file" | "directory" }> +} + +export type CommandsListInput = { + readonly location?: { + readonly location?: { readonly directory?: string | undefined; readonly workspace?: string | undefined } | undefined + }["location"] +} + +export type CommandsListOutput = { + readonly location: { + readonly directory: string + readonly workspaceID?: string + readonly project: { readonly id: string; readonly directory: string } + } + readonly data: ReadonlyArray<{ + readonly name: string + readonly template: string + readonly description?: string + readonly agent?: string + readonly model?: { readonly id: string; readonly providerID: string; readonly variant?: string } + readonly subtask?: boolean + }> +} + +export type SkillsListInput = { + readonly location?: { + readonly location?: { readonly directory?: string | undefined; readonly workspace?: string | undefined } | undefined + }["location"] +} + +export type SkillsListOutput = { + readonly location: { + readonly directory: string + readonly workspaceID?: string + readonly project: { readonly id: string; readonly directory: string } + } + readonly data: ReadonlyArray<{ + readonly name: string + readonly description?: string + readonly slash?: boolean + readonly location: string + readonly content: string + }> +} + +export type EventsSubscribeOutput = OpenCodeEventEncoded + +export type PtysListInput = { + readonly location?: { + readonly location?: { readonly directory?: string | undefined; readonly workspace?: string | undefined } | undefined + }["location"] +} + +export type PtysListOutput = { + readonly location: { + readonly directory: string + readonly workspaceID?: string + readonly project: { readonly id: string; readonly directory: string } + } + readonly data: ReadonlyArray<{ + readonly id: string + readonly title: string + readonly command: string + readonly args: ReadonlyArray + readonly cwd: string + readonly status: "running" | "exited" + readonly pid: number + readonly exitCode?: number + }> +} + +export type PtysCreateInput = { + readonly location?: { + readonly location?: { readonly directory?: string | undefined; readonly workspace?: string | undefined } | undefined + }["location"] + readonly command?: { + readonly command?: string + readonly args?: ReadonlyArray + readonly cwd?: string + readonly title?: string + readonly env?: { readonly [x: string]: string } + }["command"] + readonly args?: { + readonly command?: string + readonly args?: ReadonlyArray + readonly cwd?: string + readonly title?: string + readonly env?: { readonly [x: string]: string } + }["args"] + readonly cwd?: { + readonly command?: string + readonly args?: ReadonlyArray + readonly cwd?: string + readonly title?: string + readonly env?: { readonly [x: string]: string } + }["cwd"] + readonly title?: { + readonly command?: string + readonly args?: ReadonlyArray + readonly cwd?: string + readonly title?: string + readonly env?: { readonly [x: string]: string } + }["title"] + readonly env?: { + readonly command?: string + readonly args?: ReadonlyArray + readonly cwd?: string + readonly title?: string + readonly env?: { readonly [x: string]: string } + }["env"] +} + +export type PtysCreateOutput = { + readonly location: { + readonly directory: string + readonly workspaceID?: string + readonly project: { readonly id: string; readonly directory: string } + } + readonly data: { + readonly id: string + readonly title: string + readonly command: string + readonly args: ReadonlyArray + readonly cwd: string + readonly status: "running" | "exited" + readonly pid: number + readonly exitCode?: number + } +} + +export type PtysGetInput = { + readonly ptyID: { readonly ptyID: string }["ptyID"] + readonly location?: { + readonly location?: { readonly directory?: string | undefined; readonly workspace?: string | undefined } | undefined + }["location"] +} + +export type PtysGetOutput = { + readonly location: { + readonly directory: string + readonly workspaceID?: string + readonly project: { readonly id: string; readonly directory: string } + } + readonly data: { + readonly id: string + readonly title: string + readonly command: string + readonly args: ReadonlyArray + readonly cwd: string + readonly status: "running" | "exited" + readonly pid: number + readonly exitCode?: number + } +} + +export type PtysUpdateInput = { + readonly ptyID: { readonly ptyID: string }["ptyID"] + readonly location?: { + readonly location?: { readonly directory?: string | undefined; readonly workspace?: string | undefined } | undefined + }["location"] + readonly title?: { + readonly title?: string + readonly size?: { readonly rows: number; readonly cols: number } + }["title"] + readonly size?: { readonly title?: string; readonly size?: { readonly rows: number; readonly cols: number } }["size"] +} + +export type PtysUpdateOutput = { + readonly location: { + readonly directory: string + readonly workspaceID?: string + readonly project: { readonly id: string; readonly directory: string } + } + readonly data: { + readonly id: string + readonly title: string + readonly command: string + readonly args: ReadonlyArray + readonly cwd: string + readonly status: "running" | "exited" + readonly pid: number + readonly exitCode?: number + } +} + +export type PtysRemoveInput = { + readonly ptyID: { readonly ptyID: string }["ptyID"] + readonly location?: { + readonly location?: { readonly directory?: string | undefined; readonly workspace?: string | undefined } | undefined + }["location"] +} + +export type PtysRemoveOutput = void + +export type QuestionsListRequestsInput = { + readonly location?: { + readonly location?: { readonly directory?: string | undefined; readonly workspace?: string | undefined } | undefined + }["location"] +} + +export type QuestionsListRequestsOutput = { + readonly location: { + readonly directory: string + readonly workspaceID?: string + readonly project: { readonly id: string; readonly directory: string } + } + readonly data: ReadonlyArray<{ + readonly id: string + readonly sessionID: string + readonly questions: ReadonlyArray<{ + readonly question: string + readonly header: string + readonly options: ReadonlyArray<{ readonly label: string; readonly description: string }> + readonly multiple?: boolean + readonly custom?: boolean + }> + readonly tool?: { readonly messageID: string; readonly callID: string } + }> +} + +export type QuestionsListInput = { readonly sessionID: { readonly sessionID: string }["sessionID"] } + +export type QuestionsListOutput = { + readonly data: ReadonlyArray<{ + readonly id: string + readonly sessionID: string + readonly questions: ReadonlyArray<{ + readonly question: string + readonly header: string + readonly options: ReadonlyArray<{ readonly label: string; readonly description: string }> + readonly multiple?: boolean + readonly custom?: boolean + }> + readonly tool?: { readonly messageID: string; readonly callID: string } + }> +}["data"] + +export type QuestionsReplyInput = { + readonly sessionID: { readonly sessionID: string; readonly requestID: string }["sessionID"] + readonly requestID: { readonly sessionID: string; readonly requestID: string }["requestID"] + readonly answers: { readonly answers: ReadonlyArray> }["answers"] +} + +export type QuestionsReplyOutput = void + +export type QuestionsRejectInput = { + readonly sessionID: { readonly sessionID: string; readonly requestID: string }["sessionID"] + readonly requestID: { readonly sessionID: string; readonly requestID: string }["requestID"] +} + +export type QuestionsRejectOutput = void + +export type ReferencesListInput = { + readonly location?: { + readonly location?: { readonly directory?: string | undefined; readonly workspace?: string | undefined } | undefined + }["location"] +} + +export type ReferencesListOutput = { + readonly location: { + readonly directory: string + readonly workspaceID?: string + readonly project: { readonly id: string; readonly directory: string } + } + readonly data: ReadonlyArray<{ + readonly name: string + readonly path: string + readonly description?: string + readonly hidden?: boolean + readonly source: + | { readonly type: "local"; readonly path: string; readonly description?: string; readonly hidden?: boolean } + | { + readonly type: "git" + readonly repository: string + readonly branch?: string + readonly description?: string + readonly hidden?: boolean + } + }> +} + +export type ProjectCopiesCreateInput = { + readonly projectID: { readonly projectID: string }["projectID"] + readonly location?: { + readonly location?: { readonly directory?: string | undefined; readonly workspace?: string | undefined } | undefined + }["location"] + readonly strategy: { readonly strategy: string; readonly directory: string; readonly name?: string }["strategy"] + readonly directory: { readonly strategy: string; readonly directory: string; readonly name?: string }["directory"] + readonly name?: { readonly strategy: string; readonly directory: string; readonly name?: string }["name"] +} + +export type ProjectCopiesCreateOutput = { readonly directory: string } + +export type ProjectCopiesRemoveInput = { + readonly projectID: { readonly projectID: string }["projectID"] + readonly location?: { + readonly location?: { readonly directory?: string | undefined; readonly workspace?: string | undefined } | undefined + }["location"] + readonly directory: { readonly directory: string; readonly force: boolean }["directory"] + readonly force: { readonly directory: string; readonly force: boolean }["force"] +} + +export type ProjectCopiesRemoveOutput = void + +export type ProjectCopiesRefreshInput = { + readonly projectID: { readonly projectID: string }["projectID"] + readonly location?: { + readonly location?: { readonly directory?: string | undefined; readonly workspace?: string | undefined } | undefined + }["location"] +} + +export type ProjectCopiesRefreshOutput = void diff --git a/packages/client/test/contract-identity.test.ts b/packages/client/test/contract-identity.test.ts index e71d70751cbb..64a2e958ce2d 100644 --- a/packages/client/test/contract-identity.test.ts +++ b/packages/client/test/contract-identity.test.ts @@ -19,8 +19,7 @@ import { SessionMessage } from "@opencode-ai/schema/session-message" import { Workspace } from "@opencode-ai/schema/workspace" import { Api } from "@opencode-ai/server/api" import { compile, emitPromise } from "@opencode-ai/httpapi-codegen" -import { HttpApi } from "effect/unstable/httpapi" -import { EventGroup, SessionGroup } from "../src/contract" +import { ClientApi, endpointNames, groupNames, omitEndpoints } from "../src/contract" test("Core and Server reuse the authoritative Schema and Protocol values", () => { expect(AgentV2.ID).toBe(Agent.ID) @@ -31,18 +30,16 @@ test("Core and Server reuse the authoritative Schema and Protocol values", () => expect(CoreSessionMessage.Message).toBe(SessionMessage.Message) expect(CorePrompt).toBe(Prompt) expect(Api.groups["server.session"].identifier).toBe("server.session") - expect(SessionGroup.identifier).toBe(Api.groups["server.session"].identifier) - expect(EventGroup.identifier).toBe(Api.groups["server.event"].identifier) + expect(Object.keys(ClientApi.groups)).toEqual(Object.keys(Api.groups)) expect(Session.ID.create()).toStartWith("ses_") expect(Project.ID.global).toBe("global") expect(Provider.ID.anthropic).toBe("anthropic") expect(Workspace.ID.create()).toStartWith("wrk_") }) -test("client and Server Session contracts generate identically", () => { - const options = { groupNames: { "server.session": "sessions" } } - const server = compile(HttpApi.make("server").add(Api.groups["server.session"]), options) - const client = compile(HttpApi.make("client").add(SessionGroup), options) +test("client and Server contracts generate identically", () => { + const server = compile(Api, { groupNames, endpointNames, omitEndpoints }) + const client = compile(ClientApi, { groupNames, endpointNames, omitEndpoints }) expect(emitPromise(client)).toEqual(emitPromise(server)) }) diff --git a/packages/client/test/promise.test.ts b/packages/client/test/promise.test.ts index c5081053e5f2..322a39cd6b29 100644 --- a/packages/client/test/promise.test.ts +++ b/packages/client/test/promise.test.ts @@ -1,6 +1,43 @@ import { expect, test } from "bun:test" import { isSessionNotFoundError, isUnauthorizedError, OpenCode } from "../src" +test("exposes every standard HTTP API group", () => { + const client = OpenCode.make({ baseUrl: "http://localhost:3000" }) + + expect(Object.keys(client)).toEqual([ + "health", + "location", + "agents", + "sessions", + "messages", + "models", + "providers", + "integrations", + "credentials", + "permissions", + "files", + "commands", + "skills", + "events", + "ptys", + "questions", + "references", + "projectCopies", + ]) + expect(Object.keys(client.messages)).toEqual(["list"]) + expect(Object.keys(client.integrations)).toEqual([ + "list", + "get", + "connectKey", + "connectOauth", + "attemptStatus", + "attemptComplete", + "attemptCancel", + ]) + expect(Object.keys(client.files)).toEqual(["list", "find"]) + expect(Object.keys(client.ptys)).toEqual(["list", "create", "get", "update", "remove"]) +}) + test("sessions.get returns the wire projection", async () => { const client = OpenCode.make({ baseUrl: "http://localhost:3000", diff --git a/packages/httpapi-codegen/src/index.ts b/packages/httpapi-codegen/src/index.ts index b993926dd735..298a1211dddc 100644 --- a/packages/httpapi-codegen/src/index.ts +++ b/packages/httpapi-codegen/src/index.ts @@ -50,7 +50,7 @@ export type Endpoint = { readonly operation: Operation readonly input: ReadonlyArray readonly unwrapData: boolean - readonly errors: ReadonlyArray + readonly errors: ReadonlyArray<{ readonly status: number; readonly schema: Schema.Top }> readonly successes: ReadonlyArray readonly effectPortable: boolean } @@ -75,7 +75,11 @@ const manifestName = ".httpapi-codegen.json" export function compile( api: HttpApi.HttpApi, - options?: { readonly groupNames?: Readonly> }, + options?: { + readonly groupNames?: Readonly> + readonly endpointNames?: Readonly> + readonly omitEndpoints?: ReadonlySet + }, ): Contract { const endpoints: Array = [] const portable = new Map() @@ -83,6 +87,7 @@ export function compile( HttpApi.reflect(api, { onGroup() {}, onEndpoint({ endpoint, errors, group, middleware }) { + if (options?.omitEndpoints?.has(endpoint.name)) return const groupName = options?.groupNames?.[group.identifier] ?? group.identifier const name = `${groupName}.${endpoint.name}` const required = Array.from(middleware).find((item) => item.requiredForClient) @@ -103,8 +108,8 @@ export function compile( } const payloads = sourcePayloads.map((schema) => normalizeTransport(schema, "payload", endpoint, name)!) const success = normalizeTransport(successSchemas[0], "success", endpoint, name)! - const errorSchemas = Array.from(errors.values()).flatMap((schemas) => - schemas.map((schema) => normalizeTransport(schema, "error", endpoint, name)!), + const errorSchemas = Array.from(errors).flatMap(([status, schemas]) => + schemas.map((schema) => ({ status, ...normalizeTransport(schema, "error", endpoint, name)! })), ) const inputs = [ ...inputFields(params?.schema, "params", name), @@ -124,7 +129,7 @@ export function compile( ...(headers === undefined ? [] : [[`${name}.headers`, headers.schema] as const]), ...payloads.map((item) => [`${name}.payload`, item.schema] as const), ...responseSchemas(success.schema, `${name}.success`), - ...errorSchemas.map((item) => [`${name}.error`, item.schema] as const), + ...errorSchemas.map((item) => [`${name}.error.${item.status}`, item.schema] as const), ] const effectPortable = [params, query, headers, ...payloads, success, ...errorSchemas].every( @@ -146,11 +151,11 @@ export function compile( input: inputs, unwrapData: isDataEnvelope(success.schema), successes: [success.schema], - errors: errorSchemas.map((item) => item.schema), + errors: errorSchemas.map((item) => ({ status: item.status, schema: item.schema })), effectPortable, operation: { group: groupName, - name: clientEndpointName(endpoint.name), + name: options?.endpointNames?.[endpoint.name] ?? clientEndpointName(endpoint.name), input: inputs.map(({ name, source }) => ({ name, source })), inputMode: inputs.length === 0 ? "none" : inputs.every((field) => field.optional) ? "optional" : "required", success: isStreamSchema(success.schema) @@ -287,10 +292,10 @@ function assertPromiseEndpoint(endpoint: Endpoint) { throw new GenerationError({ reason: `Unsupported Promise success encoding: ${name}` }) } for (const error of endpoint.errors) { - if (taggedErrorFields(error) === undefined) { - throw new GenerationError({ reason: `Promise error must be tagged: ${name}` }) + if (declaredErrorFields(error.schema) === undefined) { + throw new GenerationError({ reason: `Promise error must have a literal discriminator: ${name}` }) } - if ((resolveHttpApiEncoding(error.ast)?._tag ?? "Json") !== "Json") { + if ((resolveHttpApiEncoding(error.schema.ast)?._tag ?? "Json") !== "Json") { throw new GenerationError({ reason: `Unsupported Promise error encoding: ${name}` }) } } @@ -332,7 +337,7 @@ function renderImportedEffectFiles( const fields = item.input.filter((field) => field.source === source) if (fields.length === 0) return [] return [ - `${source}: { ${fields.map((field) => `${JSON.stringify(field.name)}: input${item.operation.inputMode === "optional" ? "?." : "."}${field.name}`).join(", ")} }`, + `${source}: { ${fields.map((field) => `${JSON.stringify(field.name)}: input${item.operation.inputMode === "optional" ? "?." : ""}[${JSON.stringify(field.name)}]`).join(", ")} }`, ] }) .join(", ") @@ -429,8 +434,8 @@ function renderPromiseTypes( const errors = new Map( groups.flatMap((group) => group.endpoints.flatMap((endpoint) => - endpoint.errors.flatMap((schema) => { - const tagged = taggedErrorFields(schema) + endpoint.errors.flatMap((error) => { + const tagged = declaredErrorFields(error.schema) return tagged === undefined ? [] : [[tagged.tag, tagged] as const] }), ), @@ -440,7 +445,7 @@ function renderPromiseTypes( const fields = error.fields .map(([name, schema, optional]) => `readonly ${JSON.stringify(name)}${optional ? "?" : ""}: ${typeOf(schema)}`) .join("; ") - return `export type ${error.identifier} = { readonly _tag: ${JSON.stringify(error.tag)}; ${fields} }\nexport const is${error.identifier} = (value: unknown): value is ${error.identifier} => typeof value === "object" && value !== null && "_tag" in value && value._tag === ${JSON.stringify(error.tag)}` + return `export type ${error.identifier} = { readonly ${JSON.stringify(error.key)}: ${JSON.stringify(error.tag)}; ${fields} }\nexport const is${error.identifier} = (value: unknown): value is ${error.identifier} => typeof value === "object" && value !== null && ${JSON.stringify(error.key)} in value && value[${JSON.stringify(error.key)}] === ${JSON.stringify(error.tag)}` }) const operations = groups .flatMap((group) => @@ -499,7 +504,8 @@ function renderPromiseClient(groups: ReadonlyArray) { ? "requestOptions?: RequestOptions" : `input${endpoint.operation.inputMode === "optional" ? "?" : ""}: ${prefix}Input, requestOptions?: RequestOptions` const path = promisePath(endpoint.endpoint.path, endpoint.input) - const access = (name: string) => `input${endpoint.operation.inputMode === "optional" ? "?." : "."}${name}` + const access = (name: string) => + `input${endpoint.operation.inputMode === "optional" ? "?." : ""}[${JSON.stringify(name)}]` const part = (source: InputField["source"]) => { const inputs = endpoint.input.filter((field) => field.source === source) return inputs.length === 0 @@ -511,11 +517,7 @@ function renderPromiseClient(groups: ReadonlyArray) { endpoint.headers === undefined ? undefined : `headers: ${part("headers")}`, endpoint.payloads.length === 0 ? undefined : `body: ${part("payload")}`, ].filter((value): value is string => value !== undefined) - const declaredStatuses = [ - ...new Set( - endpoint.errors.map((schema) => resolveHttpApiStatus(schema.ast)).filter((status) => status !== undefined), - ), - ] + const declaredStatuses = [...new Set(endpoint.errors.map((error) => error.status))] const descriptor = `{ method: ${JSON.stringify(endpoint.endpoint.method)}, path: ${path}${parts.length === 0 ? "" : `, ${parts.join(", ")}`}, successStatus: ${resolveHttpApiStatus(endpoint.successes[0].ast) ?? 200}, declaredStatuses: [${declaredStatuses.join(", ")}], empty: ${endpoint.operation.success === "void"} }` if (endpoint.operation.success === "stream") { const success = endpoint.successes[0] @@ -567,9 +569,12 @@ function structuralType(schema: Schema.Top) { ) const expand = (type: string, seen = new Set()): string => { for (const [reference, value] of references) { - if (!type.includes(reference)) continue - if (seen.has(reference)) throw new GenerationError({ reason: "Recursive Promise types are not implemented" }) - type = type.replaceAll(reference, `(${expand(value, new Set([...seen, reference]))})`) + const pattern = `(?) { + if (path.includes("*")) throw new GenerationError({ reason: `Unsupported Promise path wildcard: ${path}` }) const fields = new Set(input.filter((field) => field.source === "params").map((field) => field.name)) const segments = path.split(/(:[A-Za-z_][A-Za-z0-9_]*)/g).filter(Boolean) const template = segments @@ -932,18 +938,26 @@ function serializable(value: unknown): boolean { } function taggedErrorFields(schema: Schema.Top) { + const fields = declaredErrorFields(schema) + return fields?.key === "_tag" ? fields : undefined +} + +function declaredErrorFields(schema: Schema.Top) { if (!SchemaAST.isDeclaration(schema.ast) || schema.ast.annotations?.["~effect/Schema/Class"] === undefined) { return undefined } const fields = schema.ast.typeParameters[0] if (!SchemaAST.isObjects(fields) || fields.indexSignatures.length > 0) return undefined - const tag = fields.propertySignatures.find((field) => field.name === "_tag")?.type + const key = fields.propertySignatures.find((field) => field.name === "_tag" || field.name === "name")?.name + if (key !== "_tag" && key !== "name") return undefined + const tag = fields.propertySignatures.find((field) => field.name === key)?.type if (tag === undefined || !SchemaAST.isLiteral(tag) || typeof tag.literal !== "string") return undefined return { + key, tag: tag.literal, identifier: SchemaAST.resolveIdentifier(schema.ast) ?? tag.literal, fields: fields.propertySignatures.flatMap((field) => - field.name === "_tag" || typeof field.name !== "string" + field.name === key || typeof field.name !== "string" ? [] : [[field.name, Schema.make(field.type), SchemaAST.isOptional(field.type)] as const], ), @@ -1014,7 +1028,7 @@ function renderGroup(group: Group, groupIndex: number) { const headers = addSlot(endpointHeaders, `${prefix}Headers`) const payloads = endpointPayloads.map((schema, index) => addSlot(schema, `${prefix}Payload${index}`)!) const success = renderSuccess(successes[0], `${prefix}Success`) - const errorSlots = errors.map((schema, index) => addSlot(schema, `${prefix}Error${index}`)!) + const errorSlots = errors.map((error, index) => addSlot(error.schema, `${prefix}Error${index}`)!) const options = [ params === undefined ? undefined : `params: ${params.name}`, query === undefined ? undefined : `query: ${query.name}`, diff --git a/packages/httpapi-codegen/test/generate.test.ts b/packages/httpapi-codegen/test/generate.test.ts index aa59ec60edf7..6e076b7ef4e1 100644 --- a/packages/httpapi-codegen/test/generate.test.ts +++ b/packages/httpapi-codegen/test/generate.test.ts @@ -138,6 +138,48 @@ describe("HttpApiCodegen.generate", () => { expect(contract.groups[0]?.endpoints[0]?.operation).toMatchObject({ group: "sessions", name: "get" }) }) + test("supports explicit public endpoint names", () => { + const source = HttpApi.make("test").add( + HttpApiGroup.make("server.permission") + .add(HttpApiEndpoint.get("permission.request.list", "/request", { success: Schema.String })) + .add(HttpApiEndpoint.get("session.permission.list", "/session", { success: Schema.String })), + ) + const contract = compileContract(source, { + endpointNames: { "permission.request.list": "listRequests" }, + }) + + expect(contract.groups[0]?.endpoints.map((endpoint) => endpoint.operation.name)).toEqual(["listRequests", "list"]) + }) + + test("omits custom transport endpoints", () => { + const source = HttpApi.make("test").add( + HttpApiGroup.make("server.pty") + .add(HttpApiEndpoint.get("pty.get", "/pty", { success: Schema.String })) + .add(HttpApiEndpoint.get("pty.connect", "/pty/connect", { success: Schema.Boolean })), + ) + const contract = compileContract(source, { omitEndpoints: new Set(["pty.connect"]) }) + + expect(contract.groups[0]?.endpoints.map((endpoint) => endpoint.endpoint.name)).toEqual(["pty.get"]) + }) + + test("uses bracket access for input field names", () => { + const source = api( + HttpApiEndpoint.post("token", "/token", { + headers: { "x-example-token": Schema.Literal("1") }, + success: Schema.String, + }), + ) + const contract = compileContract(source) + const promise = emitPromise(contract).files.find((file) => file.path === "client.ts")?.content + const effect = emitEffectImported(contract, { + module: "@example/api", + endpoints: { "session.token": "Token" }, + }).files.find((file) => file.path === "client.ts")?.content + + expect(promise).toContain('"x-example-token": input["x-example-token"]') + expect(effect).toContain('"x-example-token": input["x-example-token"]') + }) + test("rejects consumer group name collisions", () => { const source = HttpApi.make("test") .add(HttpApiGroup.make("first").add(HttpApiEndpoint.get("one", "/one", { success: Schema.String }))) @@ -184,6 +226,33 @@ describe("HttpApiCodegen.generate", () => { ) }) + test("supports name-discriminated Promise errors", () => { + class NamedError extends Schema.ErrorClass("NamedError")( + { name: Schema.Literal("NamedError"), message: Schema.String }, + { httpApiStatus: 400 }, + ) {} + const output = emitPromise( + compileContract( + api(HttpApiEndpoint.get("get", "/session", { success: Schema.NumberFromString, error: NamedError })), + ), + ) + const types = output.files.find((file) => file.path === "types.ts")?.content + + expect(types).toContain('readonly "name": "NamedError"') + expect(types).toContain('"name" in value && value["name"] === "NamedError"') + }) + + test("preserves reflected default error statuses", () => { + class MissingStatus extends Schema.TaggedErrorClass()("MissingStatus", { + message: Schema.String, + }) {} + const output = emitPromise( + compileContract(api(HttpApiEndpoint.get("get", "/session", { success: Schema.String, error: MissingStatus }))), + ) + + expect(output.files.find((file) => file.path === "client.ts")?.content).toContain("declaredStatuses: [500]") + }) + test("erases brands from Promise wire types", () => { const output = emitPromise( compileContract( @@ -218,6 +287,26 @@ describe("HttpApiCodegen.generate", () => { ) }) + test("expands Promise references only at identifier boundaries", () => { + const Session = Schema.Struct({ name: Schema.Literal("Session"), id: Schema.String }).annotate({ + identifier: "Session", + }) + const SessionID = Schema.String.annotate({ identifier: "SessionID" }) + const output = emitPromise( + compileContract( + api( + HttpApiEndpoint.get("get", "/session", { + success: Schema.Struct({ session: Session, sessionID: SessionID }), + }), + ), + ), + ) + + expect(output.files.find((file) => file.path === "types.ts")?.content).toContain( + 'readonly "session": ({ readonly "name": "Session", readonly "id": string })', + ) + }) + test("emits Effect Json schemas as standalone Promise types", () => { const output = emitPromise( compileContract( @@ -265,6 +354,22 @@ describe("HttpApiCodegen.generate", () => { ), ).toThrow("Unsupported Promise success encoding: session.text") + expect(() => + emitPromise( + compileContract( + api( + HttpApiEndpoint.get("binary", "/binary", { + success: Schema.Uint8Array.pipe(HttpApiSchema.asUint8Array()), + }), + ), + ), + ), + ).toThrow("Unsupported Promise success encoding: session.binary") + + expect(() => + emitPromise(compileContract(api(HttpApiEndpoint.get("read", "/file/*", { success: Schema.String })))), + ).toThrow("Unsupported Promise path wildcard: /file/*") + expect(() => emitPromise( compileContract(