diff --git a/.github/actions/setup-bun/action.yml b/.github/actions/setup-bun/action.yml index 5b44517ec51..9d29724d86a 100644 --- a/.github/actions/setup-bun/action.yml +++ b/.github/actions/setup-bun/action.yml @@ -8,6 +8,13 @@ inputs: runs: using: "composite" steps: + # node-gyp@latest (invoked via bunx for native install scripts) requires Node >=22; + # some runner images ship an older system Node on PATH + - name: Setup Node + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 + with: + node-version: "24" + - name: Get baseline download URL id: bun-url shell: bash diff --git a/packages/client/src/effect/generated/client.ts b/packages/client/src/effect/generated/client.ts index 6cce70214c0..77923e5a6cd 100644 --- a/packages/client/src/effect/generated/client.ts +++ b/packages/client/src/effect/generated/client.ts @@ -552,36 +552,129 @@ const adaptGroup12 = (raw: RawClient["server.project"]) => ({ directories: Endpoint12_1(raw), }) -type Endpoint13_0Request = Parameters[0] +type Endpoint13_0Request = Parameters[0] type Endpoint13_0Input = { readonly location?: Endpoint13_0Request["query"]["location"] } -const Endpoint13_0 = (raw: RawClient["server.permission"]) => (input?: Endpoint13_0Input) => +const Endpoint13_0 = (raw: RawClient["server.form"]) => (input?: Endpoint13_0Input) => + raw["form.request.list"]({ query: { location: input?.["location"] } }).pipe(Effect.mapError(mapClientError)) + +type Endpoint13_1Request = Parameters[0] +type Endpoint13_1Input = { readonly sessionID: Endpoint13_1Request["params"]["sessionID"] } +const Endpoint13_1 = (raw: RawClient["server.form"]) => (input: Endpoint13_1Input) => + raw["session.form.list"]({ params: { sessionID: input["sessionID"] } }).pipe( + Effect.mapError(mapClientError), + Effect.map((value) => value.data), + ) + +type Endpoint13_2Request = Parameters[0] +type Endpoint13_2Input = { + readonly sessionID: Endpoint13_2Request["params"]["sessionID"] + readonly id?: Endpoint13_2Request["payload"]["id"] + readonly title?: Endpoint13_2Request["payload"]["title"] + readonly metadata?: Endpoint13_2Request["payload"]["metadata"] + readonly mode: Endpoint13_2Request["payload"]["mode"] + readonly fields?: Endpoint13_2Request["payload"]["fields"] + readonly url?: Endpoint13_2Request["payload"]["url"] +} +const Endpoint13_2 = (raw: RawClient["server.form"]) => (input: Endpoint13_2Input) => + raw["session.form.create"]({ + params: { sessionID: input["sessionID"] }, + payload: { + id: input["id"], + title: input["title"], + metadata: input["metadata"], + mode: input["mode"], + fields: input["fields"], + url: input["url"], + }, + }).pipe( + Effect.mapError(mapClientError), + Effect.map((value) => value.data), + ) + +type Endpoint13_3Request = Parameters[0] +type Endpoint13_3Input = { + readonly sessionID: Endpoint13_3Request["params"]["sessionID"] + readonly formID: Endpoint13_3Request["params"]["formID"] +} +const Endpoint13_3 = (raw: RawClient["server.form"]) => (input: Endpoint13_3Input) => + raw["session.form.get"]({ params: { sessionID: input["sessionID"], formID: input["formID"] } }).pipe( + Effect.mapError(mapClientError), + Effect.map((value) => value.data), + ) + +type Endpoint13_4Request = Parameters[0] +type Endpoint13_4Input = { + readonly sessionID: Endpoint13_4Request["params"]["sessionID"] + readonly formID: Endpoint13_4Request["params"]["formID"] +} +const Endpoint13_4 = (raw: RawClient["server.form"]) => (input: Endpoint13_4Input) => + raw["session.form.state"]({ params: { sessionID: input["sessionID"], formID: input["formID"] } }).pipe( + Effect.mapError(mapClientError), + Effect.map((value) => value.data), + ) + +type Endpoint13_5Request = Parameters[0] +type Endpoint13_5Input = { + readonly sessionID: Endpoint13_5Request["params"]["sessionID"] + readonly formID: Endpoint13_5Request["params"]["formID"] + readonly answer: Endpoint13_5Request["payload"]["answer"] +} +const Endpoint13_5 = (raw: RawClient["server.form"]) => (input: Endpoint13_5Input) => + raw["session.form.reply"]({ + params: { sessionID: input["sessionID"], formID: input["formID"] }, + payload: { answer: input["answer"] }, + }).pipe(Effect.mapError(mapClientError)) + +type Endpoint13_6Request = Parameters[0] +type Endpoint13_6Input = { + readonly sessionID: Endpoint13_6Request["params"]["sessionID"] + readonly formID: Endpoint13_6Request["params"]["formID"] +} +const Endpoint13_6 = (raw: RawClient["server.form"]) => (input: Endpoint13_6Input) => + raw["session.form.cancel"]({ params: { sessionID: input["sessionID"], formID: input["formID"] } }).pipe( + Effect.mapError(mapClientError), + ) + +const adaptGroup13 = (raw: RawClient["server.form"]) => ({ + listRequests: Endpoint13_0(raw), + list: Endpoint13_1(raw), + create: Endpoint13_2(raw), + get: Endpoint13_3(raw), + state: Endpoint13_4(raw), + reply: Endpoint13_5(raw), + cancel: Endpoint13_6(raw), +}) + +type Endpoint14_0Request = Parameters[0] +type Endpoint14_0Input = { readonly location?: Endpoint14_0Request["query"]["location"] } +const Endpoint14_0 = (raw: RawClient["server.permission"]) => (input?: Endpoint14_0Input) => raw["permission.request.list"]({ query: { location: input?.["location"] } }).pipe(Effect.mapError(mapClientError)) -type Endpoint13_1Request = Parameters[0] -type Endpoint13_1Input = { readonly projectID?: Endpoint13_1Request["query"]["projectID"] } -const Endpoint13_1 = (raw: RawClient["server.permission"]) => (input?: Endpoint13_1Input) => +type Endpoint14_1Request = Parameters[0] +type Endpoint14_1Input = { readonly projectID?: Endpoint14_1Request["query"]["projectID"] } +const Endpoint14_1 = (raw: RawClient["server.permission"]) => (input?: Endpoint14_1Input) => raw["permission.saved.list"]({ query: { projectID: input?.["projectID"] } }).pipe( Effect.mapError(mapClientError), Effect.map((value) => value.data), ) -type Endpoint13_2Request = Parameters[0] -type Endpoint13_2Input = { readonly id: Endpoint13_2Request["params"]["id"] } -const Endpoint13_2 = (raw: RawClient["server.permission"]) => (input: Endpoint13_2Input) => +type Endpoint14_2Request = Parameters[0] +type Endpoint14_2Input = { readonly id: Endpoint14_2Request["params"]["id"] } +const Endpoint14_2 = (raw: RawClient["server.permission"]) => (input: Endpoint14_2Input) => raw["permission.saved.remove"]({ params: { id: input["id"] } }).pipe(Effect.mapError(mapClientError)) -type Endpoint13_3Request = Parameters[0] -type Endpoint13_3Input = { - readonly sessionID: Endpoint13_3Request["params"]["sessionID"] - readonly id?: Endpoint13_3Request["payload"]["id"] - readonly action: Endpoint13_3Request["payload"]["action"] - readonly resources: Endpoint13_3Request["payload"]["resources"] - readonly save?: Endpoint13_3Request["payload"]["save"] - readonly metadata?: Endpoint13_3Request["payload"]["metadata"] - readonly source?: Endpoint13_3Request["payload"]["source"] - readonly agent?: Endpoint13_3Request["payload"]["agent"] +type Endpoint14_3Request = Parameters[0] +type Endpoint14_3Input = { + readonly sessionID: Endpoint14_3Request["params"]["sessionID"] + readonly id?: Endpoint14_3Request["payload"]["id"] + readonly action: Endpoint14_3Request["payload"]["action"] + readonly resources: Endpoint14_3Request["payload"]["resources"] + readonly save?: Endpoint14_3Request["payload"]["save"] + readonly metadata?: Endpoint14_3Request["payload"]["metadata"] + readonly source?: Endpoint14_3Request["payload"]["source"] + readonly agent?: Endpoint14_3Request["payload"]["agent"] } -const Endpoint13_3 = (raw: RawClient["server.permission"]) => (input: Endpoint13_3Input) => +const Endpoint14_3 = (raw: RawClient["server.permission"]) => (input: Endpoint14_3Input) => raw["session.permission.create"]({ params: { sessionID: input["sessionID"] }, payload: { @@ -598,87 +691,87 @@ const Endpoint13_3 = (raw: RawClient["server.permission"]) => (input: Endpoint13 Effect.map((value) => value.data), ) -type Endpoint13_4Request = Parameters[0] -type Endpoint13_4Input = { readonly sessionID: Endpoint13_4Request["params"]["sessionID"] } -const Endpoint13_4 = (raw: RawClient["server.permission"]) => (input: Endpoint13_4Input) => +type Endpoint14_4Request = Parameters[0] +type Endpoint14_4Input = { readonly sessionID: Endpoint14_4Request["params"]["sessionID"] } +const Endpoint14_4 = (raw: RawClient["server.permission"]) => (input: Endpoint14_4Input) => raw["session.permission.list"]({ params: { sessionID: input["sessionID"] } }).pipe( Effect.mapError(mapClientError), Effect.map((value) => value.data), ) -type Endpoint13_5Request = Parameters[0] -type Endpoint13_5Input = { - readonly sessionID: Endpoint13_5Request["params"]["sessionID"] - readonly requestID: Endpoint13_5Request["params"]["requestID"] +type Endpoint14_5Request = Parameters[0] +type Endpoint14_5Input = { + readonly sessionID: Endpoint14_5Request["params"]["sessionID"] + readonly requestID: Endpoint14_5Request["params"]["requestID"] } -const Endpoint13_5 = (raw: RawClient["server.permission"]) => (input: Endpoint13_5Input) => +const Endpoint14_5 = (raw: RawClient["server.permission"]) => (input: Endpoint14_5Input) => raw["session.permission.get"]({ params: { sessionID: input["sessionID"], requestID: input["requestID"] } }).pipe( Effect.mapError(mapClientError), Effect.map((value) => value.data), ) -type Endpoint13_6Request = Parameters[0] -type Endpoint13_6Input = { - readonly sessionID: Endpoint13_6Request["params"]["sessionID"] - readonly requestID: Endpoint13_6Request["params"]["requestID"] - readonly reply: Endpoint13_6Request["payload"]["reply"] - readonly message?: Endpoint13_6Request["payload"]["message"] +type Endpoint14_6Request = Parameters[0] +type Endpoint14_6Input = { + readonly sessionID: Endpoint14_6Request["params"]["sessionID"] + readonly requestID: Endpoint14_6Request["params"]["requestID"] + readonly reply: Endpoint14_6Request["payload"]["reply"] + readonly message?: Endpoint14_6Request["payload"]["message"] } -const Endpoint13_6 = (raw: RawClient["server.permission"]) => (input: Endpoint13_6Input) => +const Endpoint14_6 = (raw: RawClient["server.permission"]) => (input: Endpoint14_6Input) => raw["session.permission.reply"]({ params: { sessionID: input["sessionID"], requestID: input["requestID"] }, payload: { reply: input["reply"], message: input["message"] }, }).pipe(Effect.mapError(mapClientError)) -const adaptGroup13 = (raw: RawClient["server.permission"]) => ({ - listRequests: Endpoint13_0(raw), - listSaved: Endpoint13_1(raw), - removeSaved: Endpoint13_2(raw), - create: Endpoint13_3(raw), - list: Endpoint13_4(raw), - get: Endpoint13_5(raw), - reply: Endpoint13_6(raw), +const adaptGroup14 = (raw: RawClient["server.permission"]) => ({ + listRequests: Endpoint14_0(raw), + listSaved: Endpoint14_1(raw), + removeSaved: Endpoint14_2(raw), + create: Endpoint14_3(raw), + list: Endpoint14_4(raw), + get: Endpoint14_5(raw), + reply: Endpoint14_6(raw), }) -type Endpoint14_0Request = Parameters[0] -type Endpoint14_0Input = { - readonly location?: Endpoint14_0Request["query"]["location"] - readonly path?: Endpoint14_0Request["query"]["path"] +type Endpoint15_0Request = Parameters[0] +type Endpoint15_0Input = { + readonly location?: Endpoint15_0Request["query"]["location"] + readonly path?: Endpoint15_0Request["query"]["path"] } -const Endpoint14_0 = (raw: RawClient["server.fs"]) => (input?: Endpoint14_0Input) => +const Endpoint15_0 = (raw: RawClient["server.fs"]) => (input?: Endpoint15_0Input) => raw["fs.list"]({ query: { location: input?.["location"], path: input?.["path"] } }).pipe( Effect.mapError(mapClientError), ) -type Endpoint14_1Request = Parameters[0] -type Endpoint14_1Input = { - readonly location?: Endpoint14_1Request["query"]["location"] - readonly query: Endpoint14_1Request["query"]["query"] - readonly type?: Endpoint14_1Request["query"]["type"] - readonly limit?: Endpoint14_1Request["query"]["limit"] +type Endpoint15_1Request = Parameters[0] +type Endpoint15_1Input = { + readonly location?: Endpoint15_1Request["query"]["location"] + readonly query: Endpoint15_1Request["query"]["query"] + readonly type?: Endpoint15_1Request["query"]["type"] + readonly limit?: Endpoint15_1Request["query"]["limit"] } -const Endpoint14_1 = (raw: RawClient["server.fs"]) => (input: Endpoint14_1Input) => +const Endpoint15_1 = (raw: RawClient["server.fs"]) => (input: Endpoint15_1Input) => raw["fs.find"]({ query: { location: input["location"], query: input["query"], type: input["type"], limit: input["limit"] }, }).pipe(Effect.mapError(mapClientError)) -const adaptGroup14 = (raw: RawClient["server.fs"]) => ({ list: Endpoint14_0(raw), find: Endpoint14_1(raw) }) +const adaptGroup15 = (raw: RawClient["server.fs"]) => ({ list: Endpoint15_0(raw), find: Endpoint15_1(raw) }) -type Endpoint15_0Request = Parameters[0] -type Endpoint15_0Input = { readonly location?: Endpoint15_0Request["query"]["location"] } -const Endpoint15_0 = (raw: RawClient["server.command"]) => (input?: Endpoint15_0Input) => +type Endpoint16_0Request = Parameters[0] +type Endpoint16_0Input = { readonly location?: Endpoint16_0Request["query"]["location"] } +const Endpoint16_0 = (raw: RawClient["server.command"]) => (input?: Endpoint16_0Input) => raw["command.list"]({ query: { location: input?.["location"] } }).pipe(Effect.mapError(mapClientError)) -const adaptGroup15 = (raw: RawClient["server.command"]) => ({ list: Endpoint15_0(raw) }) +const adaptGroup16 = (raw: RawClient["server.command"]) => ({ list: Endpoint16_0(raw) }) -type Endpoint16_0Request = Parameters[0] -type Endpoint16_0Input = { readonly location?: Endpoint16_0Request["query"]["location"] } -const Endpoint16_0 = (raw: RawClient["server.skill"]) => (input?: Endpoint16_0Input) => +type Endpoint17_0Request = Parameters[0] +type Endpoint17_0Input = { readonly location?: Endpoint17_0Request["query"]["location"] } +const Endpoint17_0 = (raw: RawClient["server.skill"]) => (input?: Endpoint17_0Input) => raw["skill.list"]({ query: { location: input?.["location"] } }).pipe(Effect.mapError(mapClientError)) -const adaptGroup16 = (raw: RawClient["server.skill"]) => ({ list: Endpoint16_0(raw) }) +const adaptGroup17 = (raw: RawClient["server.skill"]) => ({ list: Endpoint17_0(raw) }) -const Endpoint17_0 = (raw: RawClient["server.event"]) => () => +const Endpoint18_0 = (raw: RawClient["server.event"]) => () => Stream.unwrap( raw["event.subscribe"]({}).pipe( Effect.mapError(mapClientError), @@ -686,7 +779,7 @@ const Endpoint17_0 = (raw: RawClient["server.event"]) => () => ), ) -const Endpoint17_1 = (raw: RawClient["server.event"]) => () => +const Endpoint18_1 = (raw: RawClient["server.event"]) => () => Stream.unwrap( raw["event.changes"]({}).pipe( Effect.mapError(mapClientError), @@ -694,23 +787,23 @@ const Endpoint17_1 = (raw: RawClient["server.event"]) => () => ), ) -const adaptGroup17 = (raw: RawClient["server.event"]) => ({ subscribe: Endpoint17_0(raw), changes: Endpoint17_1(raw) }) +const adaptGroup18 = (raw: RawClient["server.event"]) => ({ subscribe: Endpoint18_0(raw), changes: Endpoint18_1(raw) }) -type Endpoint18_0Request = Parameters[0] -type Endpoint18_0Input = { readonly location?: Endpoint18_0Request["query"]["location"] } -const Endpoint18_0 = (raw: RawClient["server.pty"]) => (input?: Endpoint18_0Input) => +type Endpoint19_0Request = Parameters[0] +type Endpoint19_0Input = { readonly location?: Endpoint19_0Request["query"]["location"] } +const Endpoint19_0 = (raw: RawClient["server.pty"]) => (input?: Endpoint19_0Input) => raw["pty.list"]({ query: { location: input?.["location"] } }).pipe(Effect.mapError(mapClientError)) -type Endpoint18_1Request = Parameters[0] -type Endpoint18_1Input = { - readonly location?: Endpoint18_1Request["query"]["location"] - readonly command?: Endpoint18_1Request["payload"]["command"] - readonly args?: Endpoint18_1Request["payload"]["args"] - readonly cwd?: Endpoint18_1Request["payload"]["cwd"] - readonly title?: Endpoint18_1Request["payload"]["title"] - readonly env?: Endpoint18_1Request["payload"]["env"] +type Endpoint19_1Request = Parameters[0] +type Endpoint19_1Input = { + readonly location?: Endpoint19_1Request["query"]["location"] + readonly command?: Endpoint19_1Request["payload"]["command"] + readonly args?: Endpoint19_1Request["payload"]["args"] + readonly cwd?: Endpoint19_1Request["payload"]["cwd"] + readonly title?: Endpoint19_1Request["payload"]["title"] + readonly env?: Endpoint19_1Request["payload"]["env"] } -const Endpoint18_1 = (raw: RawClient["server.pty"]) => (input?: Endpoint18_1Input) => +const Endpoint19_1 = (raw: RawClient["server.pty"]) => (input?: Endpoint19_1Input) => raw["pty.create"]({ query: { location: input?.["location"] }, payload: { @@ -722,201 +815,201 @@ const Endpoint18_1 = (raw: RawClient["server.pty"]) => (input?: Endpoint18_1Inpu }, }).pipe(Effect.mapError(mapClientError)) -type Endpoint18_2Request = Parameters[0] -type Endpoint18_2Input = { - readonly ptyID: Endpoint18_2Request["params"]["ptyID"] - readonly location?: Endpoint18_2Request["query"]["location"] +type Endpoint19_2Request = Parameters[0] +type Endpoint19_2Input = { + readonly ptyID: Endpoint19_2Request["params"]["ptyID"] + readonly location?: Endpoint19_2Request["query"]["location"] } -const Endpoint18_2 = (raw: RawClient["server.pty"]) => (input: Endpoint18_2Input) => +const Endpoint19_2 = (raw: RawClient["server.pty"]) => (input: Endpoint19_2Input) => raw["pty.get"]({ params: { ptyID: input["ptyID"] }, query: { location: input["location"] } }).pipe( Effect.mapError(mapClientError), ) -type Endpoint18_3Request = Parameters[0] -type Endpoint18_3Input = { - readonly ptyID: Endpoint18_3Request["params"]["ptyID"] - readonly location?: Endpoint18_3Request["query"]["location"] - readonly title?: Endpoint18_3Request["payload"]["title"] - readonly size?: Endpoint18_3Request["payload"]["size"] +type Endpoint19_3Request = Parameters[0] +type Endpoint19_3Input = { + readonly ptyID: Endpoint19_3Request["params"]["ptyID"] + readonly location?: Endpoint19_3Request["query"]["location"] + readonly title?: Endpoint19_3Request["payload"]["title"] + readonly size?: Endpoint19_3Request["payload"]["size"] } -const Endpoint18_3 = (raw: RawClient["server.pty"]) => (input: Endpoint18_3Input) => +const Endpoint19_3 = (raw: RawClient["server.pty"]) => (input: Endpoint19_3Input) => raw["pty.update"]({ params: { ptyID: input["ptyID"] }, query: { location: input["location"] }, payload: { title: input["title"], size: input["size"] }, }).pipe(Effect.mapError(mapClientError)) -type Endpoint18_4Request = Parameters[0] -type Endpoint18_4Input = { - readonly ptyID: Endpoint18_4Request["params"]["ptyID"] - readonly location?: Endpoint18_4Request["query"]["location"] +type Endpoint19_4Request = Parameters[0] +type Endpoint19_4Input = { + readonly ptyID: Endpoint19_4Request["params"]["ptyID"] + readonly location?: Endpoint19_4Request["query"]["location"] } -const Endpoint18_4 = (raw: RawClient["server.pty"]) => (input: Endpoint18_4Input) => +const Endpoint19_4 = (raw: RawClient["server.pty"]) => (input: Endpoint19_4Input) => raw["pty.remove"]({ params: { ptyID: input["ptyID"] }, query: { location: input["location"] } }).pipe( Effect.mapError(mapClientError), ) -const adaptGroup18 = (raw: RawClient["server.pty"]) => ({ - list: Endpoint18_0(raw), - create: Endpoint18_1(raw), - get: Endpoint18_2(raw), - update: Endpoint18_3(raw), - remove: Endpoint18_4(raw), +const adaptGroup19 = (raw: RawClient["server.pty"]) => ({ + list: Endpoint19_0(raw), + create: Endpoint19_1(raw), + get: Endpoint19_2(raw), + update: Endpoint19_3(raw), + remove: Endpoint19_4(raw), }) -type Endpoint19_0Request = Parameters[0] -type Endpoint19_0Input = { readonly location?: Endpoint19_0Request["query"]["location"] } -const Endpoint19_0 = (raw: RawClient["server.shell"]) => (input?: Endpoint19_0Input) => +type Endpoint20_0Request = Parameters[0] +type Endpoint20_0Input = { readonly location?: Endpoint20_0Request["query"]["location"] } +const Endpoint20_0 = (raw: RawClient["server.shell"]) => (input?: Endpoint20_0Input) => raw["shell.list"]({ query: { location: input?.["location"] } }).pipe(Effect.mapError(mapClientError)) -type Endpoint19_1Request = Parameters[0] -type Endpoint19_1Input = { - readonly location?: Endpoint19_1Request["query"]["location"] - readonly command: Endpoint19_1Request["payload"]["command"] - readonly cwd?: Endpoint19_1Request["payload"]["cwd"] - readonly timeout?: Endpoint19_1Request["payload"]["timeout"] - readonly metadata?: Endpoint19_1Request["payload"]["metadata"] +type Endpoint20_1Request = Parameters[0] +type Endpoint20_1Input = { + readonly location?: Endpoint20_1Request["query"]["location"] + readonly command: Endpoint20_1Request["payload"]["command"] + readonly cwd?: Endpoint20_1Request["payload"]["cwd"] + readonly timeout?: Endpoint20_1Request["payload"]["timeout"] + readonly metadata?: Endpoint20_1Request["payload"]["metadata"] } -const Endpoint19_1 = (raw: RawClient["server.shell"]) => (input: Endpoint19_1Input) => +const Endpoint20_1 = (raw: RawClient["server.shell"]) => (input: Endpoint20_1Input) => raw["shell.create"]({ query: { location: input["location"] }, payload: { command: input["command"], cwd: input["cwd"], timeout: input["timeout"], metadata: input["metadata"] }, }).pipe(Effect.mapError(mapClientError)) -type Endpoint19_2Request = Parameters[0] -type Endpoint19_2Input = { - readonly id: Endpoint19_2Request["params"]["id"] - readonly location?: Endpoint19_2Request["query"]["location"] +type Endpoint20_2Request = Parameters[0] +type Endpoint20_2Input = { + readonly id: Endpoint20_2Request["params"]["id"] + readonly location?: Endpoint20_2Request["query"]["location"] } -const Endpoint19_2 = (raw: RawClient["server.shell"]) => (input: Endpoint19_2Input) => +const Endpoint20_2 = (raw: RawClient["server.shell"]) => (input: Endpoint20_2Input) => raw["shell.get"]({ params: { id: input["id"] }, query: { location: input["location"] } }).pipe( Effect.mapError(mapClientError), ) -type Endpoint19_3Request = Parameters[0] -type Endpoint19_3Input = { - readonly id: Endpoint19_3Request["params"]["id"] - readonly location?: Endpoint19_3Request["query"]["location"] - readonly cursor?: Endpoint19_3Request["query"]["cursor"] - readonly limit?: Endpoint19_3Request["query"]["limit"] +type Endpoint20_3Request = Parameters[0] +type Endpoint20_3Input = { + readonly id: Endpoint20_3Request["params"]["id"] + readonly location?: Endpoint20_3Request["query"]["location"] + readonly cursor?: Endpoint20_3Request["query"]["cursor"] + readonly limit?: Endpoint20_3Request["query"]["limit"] } -const Endpoint19_3 = (raw: RawClient["server.shell"]) => (input: Endpoint19_3Input) => +const Endpoint20_3 = (raw: RawClient["server.shell"]) => (input: Endpoint20_3Input) => raw["shell.output"]({ params: { id: input["id"] }, query: { location: input["location"], cursor: input["cursor"], limit: input["limit"] }, }).pipe(Effect.mapError(mapClientError)) -type Endpoint19_4Request = Parameters[0] -type Endpoint19_4Input = { - readonly id: Endpoint19_4Request["params"]["id"] - readonly location?: Endpoint19_4Request["query"]["location"] +type Endpoint20_4Request = Parameters[0] +type Endpoint20_4Input = { + readonly id: Endpoint20_4Request["params"]["id"] + readonly location?: Endpoint20_4Request["query"]["location"] } -const Endpoint19_4 = (raw: RawClient["server.shell"]) => (input: Endpoint19_4Input) => +const Endpoint20_4 = (raw: RawClient["server.shell"]) => (input: Endpoint20_4Input) => raw["shell.remove"]({ params: { id: input["id"] }, query: { location: input["location"] } }).pipe( Effect.mapError(mapClientError), ) -const adaptGroup19 = (raw: RawClient["server.shell"]) => ({ - list: Endpoint19_0(raw), - create: Endpoint19_1(raw), - get: Endpoint19_2(raw), - output: Endpoint19_3(raw), - remove: Endpoint19_4(raw), +const adaptGroup20 = (raw: RawClient["server.shell"]) => ({ + list: Endpoint20_0(raw), + create: Endpoint20_1(raw), + get: Endpoint20_2(raw), + output: Endpoint20_3(raw), + remove: Endpoint20_4(raw), }) -type Endpoint20_0Request = Parameters[0] -type Endpoint20_0Input = { readonly location?: Endpoint20_0Request["query"]["location"] } -const Endpoint20_0 = (raw: RawClient["server.question"]) => (input?: Endpoint20_0Input) => +type Endpoint21_0Request = Parameters[0] +type Endpoint21_0Input = { readonly location?: Endpoint21_0Request["query"]["location"] } +const Endpoint21_0 = (raw: RawClient["server.question"]) => (input?: Endpoint21_0Input) => raw["question.request.list"]({ query: { location: input?.["location"] } }).pipe(Effect.mapError(mapClientError)) -type Endpoint20_1Request = Parameters[0] -type Endpoint20_1Input = { readonly sessionID: Endpoint20_1Request["params"]["sessionID"] } -const Endpoint20_1 = (raw: RawClient["server.question"]) => (input: Endpoint20_1Input) => +type Endpoint21_1Request = Parameters[0] +type Endpoint21_1Input = { readonly sessionID: Endpoint21_1Request["params"]["sessionID"] } +const Endpoint21_1 = (raw: RawClient["server.question"]) => (input: Endpoint21_1Input) => raw["session.question.list"]({ params: { sessionID: input["sessionID"] } }).pipe( Effect.mapError(mapClientError), Effect.map((value) => value.data), ) -type Endpoint20_2Request = Parameters[0] -type Endpoint20_2Input = { - readonly sessionID: Endpoint20_2Request["params"]["sessionID"] - readonly requestID: Endpoint20_2Request["params"]["requestID"] - readonly answers: Endpoint20_2Request["payload"]["answers"] +type Endpoint21_2Request = Parameters[0] +type Endpoint21_2Input = { + readonly sessionID: Endpoint21_2Request["params"]["sessionID"] + readonly requestID: Endpoint21_2Request["params"]["requestID"] + readonly answers: Endpoint21_2Request["payload"]["answers"] } -const Endpoint20_2 = (raw: RawClient["server.question"]) => (input: Endpoint20_2Input) => +const Endpoint21_2 = (raw: RawClient["server.question"]) => (input: Endpoint21_2Input) => raw["session.question.reply"]({ params: { sessionID: input["sessionID"], requestID: input["requestID"] }, payload: { answers: input["answers"] }, }).pipe(Effect.mapError(mapClientError)) -type Endpoint20_3Request = Parameters[0] -type Endpoint20_3Input = { - readonly sessionID: Endpoint20_3Request["params"]["sessionID"] - readonly requestID: Endpoint20_3Request["params"]["requestID"] +type Endpoint21_3Request = Parameters[0] +type Endpoint21_3Input = { + readonly sessionID: Endpoint21_3Request["params"]["sessionID"] + readonly requestID: Endpoint21_3Request["params"]["requestID"] } -const Endpoint20_3 = (raw: RawClient["server.question"]) => (input: Endpoint20_3Input) => +const Endpoint21_3 = (raw: RawClient["server.question"]) => (input: Endpoint21_3Input) => raw["session.question.reject"]({ params: { sessionID: input["sessionID"], requestID: input["requestID"] } }).pipe( Effect.mapError(mapClientError), ) -const adaptGroup20 = (raw: RawClient["server.question"]) => ({ - listRequests: Endpoint20_0(raw), - list: Endpoint20_1(raw), - reply: Endpoint20_2(raw), - reject: Endpoint20_3(raw), +const adaptGroup21 = (raw: RawClient["server.question"]) => ({ + listRequests: Endpoint21_0(raw), + list: Endpoint21_1(raw), + reply: Endpoint21_2(raw), + reject: Endpoint21_3(raw), }) -type Endpoint21_0Request = Parameters[0] -type Endpoint21_0Input = { readonly location?: Endpoint21_0Request["query"]["location"] } -const Endpoint21_0 = (raw: RawClient["server.reference"]) => (input?: Endpoint21_0Input) => +type Endpoint22_0Request = Parameters[0] +type Endpoint22_0Input = { readonly location?: Endpoint22_0Request["query"]["location"] } +const Endpoint22_0 = (raw: RawClient["server.reference"]) => (input?: Endpoint22_0Input) => raw["reference.list"]({ query: { location: input?.["location"] } }).pipe(Effect.mapError(mapClientError)) -const adaptGroup21 = (raw: RawClient["server.reference"]) => ({ list: Endpoint21_0(raw) }) +const adaptGroup22 = (raw: RawClient["server.reference"]) => ({ list: Endpoint22_0(raw) }) -type Endpoint22_0Request = Parameters[0] -type Endpoint22_0Input = { - readonly projectID: Endpoint22_0Request["params"]["projectID"] - readonly location?: Endpoint22_0Request["query"]["location"] - readonly strategy: Endpoint22_0Request["payload"]["strategy"] - readonly directory: Endpoint22_0Request["payload"]["directory"] - readonly name?: Endpoint22_0Request["payload"]["name"] +type Endpoint23_0Request = Parameters[0] +type Endpoint23_0Input = { + readonly projectID: Endpoint23_0Request["params"]["projectID"] + readonly location?: Endpoint23_0Request["query"]["location"] + readonly strategy: Endpoint23_0Request["payload"]["strategy"] + readonly directory: Endpoint23_0Request["payload"]["directory"] + readonly name?: Endpoint23_0Request["payload"]["name"] } -const Endpoint22_0 = (raw: RawClient["server.projectCopy"]) => (input: Endpoint22_0Input) => +const Endpoint23_0 = (raw: RawClient["server.projectCopy"]) => (input: Endpoint23_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 Endpoint22_1Request = Parameters[0] -type Endpoint22_1Input = { - readonly projectID: Endpoint22_1Request["params"]["projectID"] - readonly location?: Endpoint22_1Request["query"]["location"] - readonly directory: Endpoint22_1Request["payload"]["directory"] - readonly force: Endpoint22_1Request["payload"]["force"] +type Endpoint23_1Request = Parameters[0] +type Endpoint23_1Input = { + readonly projectID: Endpoint23_1Request["params"]["projectID"] + readonly location?: Endpoint23_1Request["query"]["location"] + readonly directory: Endpoint23_1Request["payload"]["directory"] + readonly force: Endpoint23_1Request["payload"]["force"] } -const Endpoint22_1 = (raw: RawClient["server.projectCopy"]) => (input: Endpoint22_1Input) => +const Endpoint23_1 = (raw: RawClient["server.projectCopy"]) => (input: Endpoint23_1Input) => raw["projectCopy.remove"]({ params: { projectID: input["projectID"] }, query: { location: input["location"] }, payload: { directory: input["directory"], force: input["force"] }, }).pipe(Effect.mapError(mapClientError)) -type Endpoint22_2Request = Parameters[0] -type Endpoint22_2Input = { - readonly projectID: Endpoint22_2Request["params"]["projectID"] - readonly location?: Endpoint22_2Request["query"]["location"] +type Endpoint23_2Request = Parameters[0] +type Endpoint23_2Input = { + readonly projectID: Endpoint23_2Request["params"]["projectID"] + readonly location?: Endpoint23_2Request["query"]["location"] } -const Endpoint22_2 = (raw: RawClient["server.projectCopy"]) => (input: Endpoint22_2Input) => +const Endpoint23_2 = (raw: RawClient["server.projectCopy"]) => (input: Endpoint23_2Input) => raw["projectCopy.refresh"]({ params: { projectID: input["projectID"] }, query: { location: input["location"] }, }).pipe(Effect.mapError(mapClientError)) -const adaptGroup22 = (raw: RawClient["server.projectCopy"]) => ({ - create: Endpoint22_0(raw), - remove: Endpoint22_1(raw), - refresh: Endpoint22_2(raw), +const adaptGroup23 = (raw: RawClient["server.projectCopy"]) => ({ + create: Endpoint23_0(raw), + remove: Endpoint23_1(raw), + refresh: Endpoint23_2(raw), }) const adaptClient = (raw: RawClient) => ({ @@ -933,16 +1026,17 @@ const adaptClient = (raw: RawClient) => ({ "server.mcp": adaptGroup10(raw["server.mcp"]), credential: adaptGroup11(raw["server.credential"]), project: adaptGroup12(raw["server.project"]), - permission: adaptGroup13(raw["server.permission"]), - file: adaptGroup14(raw["server.fs"]), - command: adaptGroup15(raw["server.command"]), - skill: adaptGroup16(raw["server.skill"]), - event: adaptGroup17(raw["server.event"]), - pty: adaptGroup18(raw["server.pty"]), - shell: adaptGroup19(raw["server.shell"]), - question: adaptGroup20(raw["server.question"]), - reference: adaptGroup21(raw["server.reference"]), - projectCopy: adaptGroup22(raw["server.projectCopy"]), + form: adaptGroup13(raw["server.form"]), + permission: adaptGroup14(raw["server.permission"]), + file: adaptGroup15(raw["server.fs"]), + command: adaptGroup16(raw["server.command"]), + skill: adaptGroup17(raw["server.skill"]), + event: adaptGroup18(raw["server.event"]), + pty: adaptGroup19(raw["server.pty"]), + shell: adaptGroup20(raw["server.shell"]), + question: adaptGroup21(raw["server.question"]), + reference: adaptGroup22(raw["server.reference"]), + projectCopy: adaptGroup23(raw["server.projectCopy"]), }) export const make = (options?: { readonly baseUrl?: URL | string }) => diff --git a/packages/client/src/effect/index.ts b/packages/client/src/effect/index.ts index 38bae4d7535..1a69a358cc6 100644 --- a/packages/client/src/effect/index.ts +++ b/packages/client/src/effect/index.ts @@ -9,6 +9,7 @@ export { Credential } from "@opencode-ai/schema/credential" export { Event } from "@opencode-ai/schema/event" export { EventLog } from "@opencode-ai/schema/event-log" export { FileSystem } from "@opencode-ai/schema/filesystem" +export { Form } from "@opencode-ai/schema/form" export { Integration } from "@opencode-ai/schema/integration" export { Location } from "@opencode-ai/schema/location" export { Model } from "@opencode-ai/schema/model" diff --git a/packages/client/src/promise/generated/client.ts b/packages/client/src/promise/generated/client.ts index b2278921c5c..46522256bc5 100644 --- a/packages/client/src/promise/generated/client.ts +++ b/packages/client/src/promise/generated/client.ts @@ -91,6 +91,20 @@ import type { ProjectCurrentOutput, ProjectDirectoriesInput, ProjectDirectoriesOutput, + FormListRequestsInput, + FormListRequestsOutput, + FormListInput, + FormListOutput, + FormCreateInput, + FormCreateOutput, + FormGetInput, + FormGetOutput, + FormStateInput, + FormStateOutput, + FormReplyInput, + FormReplyOutput, + FormCancelInput, + FormCancelOutput, PermissionListRequestsInput, PermissionListRequestsOutput, PermissionListSavedInput, @@ -891,6 +905,95 @@ export function make(options: ClientOptions) { requestOptions, ), }, + form: { + listRequests: (input?: FormListRequestsInput, requestOptions?: RequestOptions) => + request( + { + method: "GET", + path: `/api/form/request`, + query: { location: input?.["location"] }, + successStatus: 200, + declaredStatuses: [401, 400], + empty: false, + }, + requestOptions, + ), + list: (input: FormListInput, requestOptions?: RequestOptions) => + request<{ readonly data: FormListOutput }>( + { + method: "GET", + path: `/api/session/${encodeURIComponent(input.sessionID)}/form`, + successStatus: 200, + declaredStatuses: [404, 400, 401], + empty: false, + }, + requestOptions, + ).then((value) => value.data), + create: (input: FormCreateInput, requestOptions?: RequestOptions) => + request<{ readonly data: FormCreateOutput }>( + { + method: "POST", + path: `/api/session/${encodeURIComponent(input.sessionID)}/form`, + body: { + id: input["id"], + title: input["title"], + metadata: input["metadata"], + mode: input["mode"], + fields: input["fields"], + url: input["url"], + }, + successStatus: 200, + declaredStatuses: [404, 409, 400, 401], + empty: false, + }, + requestOptions, + ).then((value) => value.data), + get: (input: FormGetInput, requestOptions?: RequestOptions) => + request<{ readonly data: FormGetOutput }>( + { + method: "GET", + path: `/api/session/${encodeURIComponent(input.sessionID)}/form/${encodeURIComponent(input.formID)}`, + successStatus: 200, + declaredStatuses: [404, 400, 401], + empty: false, + }, + requestOptions, + ).then((value) => value.data), + state: (input: FormStateInput, requestOptions?: RequestOptions) => + request<{ readonly data: FormStateOutput }>( + { + method: "GET", + path: `/api/session/${encodeURIComponent(input.sessionID)}/form/${encodeURIComponent(input.formID)}/state`, + successStatus: 200, + declaredStatuses: [404, 400, 401], + empty: false, + }, + requestOptions, + ).then((value) => value.data), + reply: (input: FormReplyInput, requestOptions?: RequestOptions) => + request( + { + method: "POST", + path: `/api/session/${encodeURIComponent(input.sessionID)}/form/${encodeURIComponent(input.formID)}/reply`, + body: { answer: input["answer"] }, + successStatus: 204, + declaredStatuses: [404, 409, 400, 401], + empty: true, + }, + requestOptions, + ), + cancel: (input: FormCancelInput, requestOptions?: RequestOptions) => + request( + { + method: "POST", + path: `/api/session/${encodeURIComponent(input.sessionID)}/form/${encodeURIComponent(input.formID)}/cancel`, + successStatus: 204, + declaredStatuses: [404, 409, 400, 401], + empty: true, + }, + requestOptions, + ), + }, permission: { listRequests: (input?: PermissionListRequestsInput, requestOptions?: RequestOptions) => request( diff --git a/packages/client/src/promise/generated/types.ts b/packages/client/src/promise/generated/types.ts index 76b0304efa2..a08a3889b4f 100644 --- a/packages/client/src/promise/generated/types.ts +++ b/packages/client/src/promise/generated/types.ts @@ -106,6 +106,26 @@ export type ProviderNotFoundError = { export const isProviderNotFoundError = (value: unknown): value is ProviderNotFoundError => typeof value === "object" && value !== null && "_tag" in value && value["_tag"] === "ProviderNotFoundError" +export type FormNotFoundError = { readonly _tag: "FormNotFoundError"; readonly id: string; readonly message: string } +export const isFormNotFoundError = (value: unknown): value is FormNotFoundError => + typeof value === "object" && value !== null && "_tag" in value && value["_tag"] === "FormNotFoundError" + +export type FormAlreadySettledError = { + readonly _tag: "FormAlreadySettledError" + readonly id: string + readonly message: string +} +export const isFormAlreadySettledError = (value: unknown): value is FormAlreadySettledError => + typeof value === "object" && value !== null && "_tag" in value && value["_tag"] === "FormAlreadySettledError" + +export type FormInvalidAnswerError = { + readonly _tag: "FormInvalidAnswerError" + readonly id: string + readonly message: string +} +export const isFormInvalidAnswerError = (value: unknown): value is FormInvalidAnswerError => + typeof value === "object" && value !== null && "_tag" in value && value["_tag"] === "FormInvalidAnswerError" + export type PermissionNotFoundError = { readonly _tag: "PermissionNotFoundError" readonly requestID: string @@ -2408,6 +2428,880 @@ export type ProjectDirectoriesInput = { export type ProjectDirectoriesOutput = ReadonlyArray<{ readonly directory: string; readonly strategy?: string }> +export type FormListRequestsInput = { + readonly location?: { + readonly location?: { readonly directory?: string | undefined; readonly workspace?: string | undefined } | undefined + }["location"] +} + +export type FormListRequestsOutput = { + 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 title?: string + readonly metadata?: { readonly [x: string]: JsonValue } + readonly mode: "form" + readonly fields: ReadonlyArray< + | { + readonly key: string + readonly title?: string + readonly description?: string + readonly required?: boolean + readonly when?: { readonly key: string; readonly op: "eq" | "neq"; readonly value: string } + readonly type: "string" + readonly format?: "email" | "uri" | "date" | "date-time" + readonly minLength?: number + readonly maxLength?: number + readonly pattern?: string + readonly placeholder?: string + readonly default?: string + readonly options?: ReadonlyArray<{ + readonly value: string + readonly label: string + readonly description?: string + }> + readonly custom?: boolean + } + | { + readonly key: string + readonly title?: string + readonly description?: string + readonly required?: boolean + readonly when?: { readonly key: string; readonly op: "eq" | "neq"; readonly value: string } + readonly type: "number" + readonly minimum?: number | "Infinity" | "-Infinity" | "NaN" + readonly maximum?: number | "Infinity" | "-Infinity" | "NaN" + readonly default?: number | "Infinity" | "-Infinity" | "NaN" + } + | { + readonly key: string + readonly title?: string + readonly description?: string + readonly required?: boolean + readonly when?: { readonly key: string; readonly op: "eq" | "neq"; readonly value: string } + readonly type: "integer" + readonly minimum?: number | "Infinity" | "-Infinity" | "NaN" + readonly maximum?: number | "Infinity" | "-Infinity" | "NaN" + readonly default?: number | "Infinity" | "-Infinity" | "NaN" + } + | { + readonly key: string + readonly title?: string + readonly description?: string + readonly required?: boolean + readonly when?: { readonly key: string; readonly op: "eq" | "neq"; readonly value: string } + readonly type: "boolean" + readonly default?: boolean + } + | { + readonly key: string + readonly title?: string + readonly description?: string + readonly required?: boolean + readonly when?: { readonly key: string; readonly op: "eq" | "neq"; readonly value: string } + readonly type: "multiselect" + readonly options: ReadonlyArray<{ + readonly value: string + readonly label: string + readonly description?: string + }> + readonly minItems?: number + readonly maxItems?: number + readonly custom?: boolean + readonly default?: ReadonlyArray + } + > + } + | { + readonly id: string + readonly sessionID: string + readonly title?: string + readonly metadata?: { readonly [x: string]: JsonValue } + readonly mode: "url" + readonly url: string + } + > +} + +export type FormListInput = { readonly sessionID: { readonly sessionID: string }["sessionID"] } + +export type FormListOutput = { + readonly data: ReadonlyArray< + | { + readonly id: string + readonly sessionID: string + readonly title?: string + readonly metadata?: { readonly [x: string]: JsonValue } + readonly mode: "form" + readonly fields: ReadonlyArray< + | { + readonly key: string + readonly title?: string + readonly description?: string + readonly required?: boolean + readonly when?: { readonly key: string; readonly op: "eq" | "neq"; readonly value: string } + readonly type: "string" + readonly format?: "email" | "uri" | "date" | "date-time" + readonly minLength?: number + readonly maxLength?: number + readonly pattern?: string + readonly placeholder?: string + readonly default?: string + readonly options?: ReadonlyArray<{ + readonly value: string + readonly label: string + readonly description?: string + }> + readonly custom?: boolean + } + | { + readonly key: string + readonly title?: string + readonly description?: string + readonly required?: boolean + readonly when?: { readonly key: string; readonly op: "eq" | "neq"; readonly value: string } + readonly type: "number" + readonly minimum?: number | "Infinity" | "-Infinity" | "NaN" + readonly maximum?: number | "Infinity" | "-Infinity" | "NaN" + readonly default?: number | "Infinity" | "-Infinity" | "NaN" + } + | { + readonly key: string + readonly title?: string + readonly description?: string + readonly required?: boolean + readonly when?: { readonly key: string; readonly op: "eq" | "neq"; readonly value: string } + readonly type: "integer" + readonly minimum?: number | "Infinity" | "-Infinity" | "NaN" + readonly maximum?: number | "Infinity" | "-Infinity" | "NaN" + readonly default?: number | "Infinity" | "-Infinity" | "NaN" + } + | { + readonly key: string + readonly title?: string + readonly description?: string + readonly required?: boolean + readonly when?: { readonly key: string; readonly op: "eq" | "neq"; readonly value: string } + readonly type: "boolean" + readonly default?: boolean + } + | { + readonly key: string + readonly title?: string + readonly description?: string + readonly required?: boolean + readonly when?: { readonly key: string; readonly op: "eq" | "neq"; readonly value: string } + readonly type: "multiselect" + readonly options: ReadonlyArray<{ + readonly value: string + readonly label: string + readonly description?: string + }> + readonly minItems?: number + readonly maxItems?: number + readonly custom?: boolean + readonly default?: ReadonlyArray + } + > + } + | { + readonly id: string + readonly sessionID: string + readonly title?: string + readonly metadata?: { readonly [x: string]: JsonValue } + readonly mode: "url" + readonly url: string + } + > +}["data"] + +export type FormCreateInput = { + readonly sessionID: { readonly sessionID: string }["sessionID"] + readonly id?: { + readonly id?: string | null + readonly title?: string + readonly metadata?: { readonly [x: string]: JsonValue } + readonly mode: "form" | "url" + readonly fields?: ReadonlyArray< + | { + readonly key: string + readonly title?: string + readonly description?: string + readonly required?: boolean + readonly when?: { readonly key: string; readonly op: "eq" | "neq"; readonly value: string } + readonly type: "string" + readonly format?: "email" | "uri" | "date" | "date-time" + readonly minLength?: number + readonly maxLength?: number + readonly pattern?: string + readonly placeholder?: string + readonly default?: string + readonly options?: ReadonlyArray<{ + readonly value: string + readonly label: string + readonly description?: string + }> + readonly custom?: boolean + } + | { + readonly key: string + readonly title?: string + readonly description?: string + readonly required?: boolean + readonly when?: { readonly key: string; readonly op: "eq" | "neq"; readonly value: string } + readonly type: "number" + readonly minimum?: number | "Infinity" | "-Infinity" | "NaN" + readonly maximum?: number | "Infinity" | "-Infinity" | "NaN" + readonly default?: number | "Infinity" | "-Infinity" | "NaN" + } + | { + readonly key: string + readonly title?: string + readonly description?: string + readonly required?: boolean + readonly when?: { readonly key: string; readonly op: "eq" | "neq"; readonly value: string } + readonly type: "integer" + readonly minimum?: number | "Infinity" | "-Infinity" | "NaN" + readonly maximum?: number | "Infinity" | "-Infinity" | "NaN" + readonly default?: number | "Infinity" | "-Infinity" | "NaN" + } + | { + readonly key: string + readonly title?: string + readonly description?: string + readonly required?: boolean + readonly when?: { readonly key: string; readonly op: "eq" | "neq"; readonly value: string } + readonly type: "boolean" + readonly default?: boolean + } + | { + readonly key: string + readonly title?: string + readonly description?: string + readonly required?: boolean + readonly when?: { readonly key: string; readonly op: "eq" | "neq"; readonly value: string } + readonly type: "multiselect" + readonly options: ReadonlyArray<{ + readonly value: string + readonly label: string + readonly description?: string + }> + readonly minItems?: number + readonly maxItems?: number + readonly custom?: boolean + readonly default?: ReadonlyArray + } + > | null + readonly url?: string | null + }["id"] + readonly title?: { + readonly id?: string | null + readonly title?: string + readonly metadata?: { readonly [x: string]: JsonValue } + readonly mode: "form" | "url" + readonly fields?: ReadonlyArray< + | { + readonly key: string + readonly title?: string + readonly description?: string + readonly required?: boolean + readonly when?: { readonly key: string; readonly op: "eq" | "neq"; readonly value: string } + readonly type: "string" + readonly format?: "email" | "uri" | "date" | "date-time" + readonly minLength?: number + readonly maxLength?: number + readonly pattern?: string + readonly placeholder?: string + readonly default?: string + readonly options?: ReadonlyArray<{ + readonly value: string + readonly label: string + readonly description?: string + }> + readonly custom?: boolean + } + | { + readonly key: string + readonly title?: string + readonly description?: string + readonly required?: boolean + readonly when?: { readonly key: string; readonly op: "eq" | "neq"; readonly value: string } + readonly type: "number" + readonly minimum?: number | "Infinity" | "-Infinity" | "NaN" + readonly maximum?: number | "Infinity" | "-Infinity" | "NaN" + readonly default?: number | "Infinity" | "-Infinity" | "NaN" + } + | { + readonly key: string + readonly title?: string + readonly description?: string + readonly required?: boolean + readonly when?: { readonly key: string; readonly op: "eq" | "neq"; readonly value: string } + readonly type: "integer" + readonly minimum?: number | "Infinity" | "-Infinity" | "NaN" + readonly maximum?: number | "Infinity" | "-Infinity" | "NaN" + readonly default?: number | "Infinity" | "-Infinity" | "NaN" + } + | { + readonly key: string + readonly title?: string + readonly description?: string + readonly required?: boolean + readonly when?: { readonly key: string; readonly op: "eq" | "neq"; readonly value: string } + readonly type: "boolean" + readonly default?: boolean + } + | { + readonly key: string + readonly title?: string + readonly description?: string + readonly required?: boolean + readonly when?: { readonly key: string; readonly op: "eq" | "neq"; readonly value: string } + readonly type: "multiselect" + readonly options: ReadonlyArray<{ + readonly value: string + readonly label: string + readonly description?: string + }> + readonly minItems?: number + readonly maxItems?: number + readonly custom?: boolean + readonly default?: ReadonlyArray + } + > | null + readonly url?: string | null + }["title"] + readonly metadata?: { + readonly id?: string | null + readonly title?: string + readonly metadata?: { readonly [x: string]: JsonValue } + readonly mode: "form" | "url" + readonly fields?: ReadonlyArray< + | { + readonly key: string + readonly title?: string + readonly description?: string + readonly required?: boolean + readonly when?: { readonly key: string; readonly op: "eq" | "neq"; readonly value: string } + readonly type: "string" + readonly format?: "email" | "uri" | "date" | "date-time" + readonly minLength?: number + readonly maxLength?: number + readonly pattern?: string + readonly placeholder?: string + readonly default?: string + readonly options?: ReadonlyArray<{ + readonly value: string + readonly label: string + readonly description?: string + }> + readonly custom?: boolean + } + | { + readonly key: string + readonly title?: string + readonly description?: string + readonly required?: boolean + readonly when?: { readonly key: string; readonly op: "eq" | "neq"; readonly value: string } + readonly type: "number" + readonly minimum?: number | "Infinity" | "-Infinity" | "NaN" + readonly maximum?: number | "Infinity" | "-Infinity" | "NaN" + readonly default?: number | "Infinity" | "-Infinity" | "NaN" + } + | { + readonly key: string + readonly title?: string + readonly description?: string + readonly required?: boolean + readonly when?: { readonly key: string; readonly op: "eq" | "neq"; readonly value: string } + readonly type: "integer" + readonly minimum?: number | "Infinity" | "-Infinity" | "NaN" + readonly maximum?: number | "Infinity" | "-Infinity" | "NaN" + readonly default?: number | "Infinity" | "-Infinity" | "NaN" + } + | { + readonly key: string + readonly title?: string + readonly description?: string + readonly required?: boolean + readonly when?: { readonly key: string; readonly op: "eq" | "neq"; readonly value: string } + readonly type: "boolean" + readonly default?: boolean + } + | { + readonly key: string + readonly title?: string + readonly description?: string + readonly required?: boolean + readonly when?: { readonly key: string; readonly op: "eq" | "neq"; readonly value: string } + readonly type: "multiselect" + readonly options: ReadonlyArray<{ + readonly value: string + readonly label: string + readonly description?: string + }> + readonly minItems?: number + readonly maxItems?: number + readonly custom?: boolean + readonly default?: ReadonlyArray + } + > | null + readonly url?: string | null + }["metadata"] + readonly mode: { + readonly id?: string | null + readonly title?: string + readonly metadata?: { readonly [x: string]: JsonValue } + readonly mode: "form" | "url" + readonly fields?: ReadonlyArray< + | { + readonly key: string + readonly title?: string + readonly description?: string + readonly required?: boolean + readonly when?: { readonly key: string; readonly op: "eq" | "neq"; readonly value: string } + readonly type: "string" + readonly format?: "email" | "uri" | "date" | "date-time" + readonly minLength?: number + readonly maxLength?: number + readonly pattern?: string + readonly placeholder?: string + readonly default?: string + readonly options?: ReadonlyArray<{ + readonly value: string + readonly label: string + readonly description?: string + }> + readonly custom?: boolean + } + | { + readonly key: string + readonly title?: string + readonly description?: string + readonly required?: boolean + readonly when?: { readonly key: string; readonly op: "eq" | "neq"; readonly value: string } + readonly type: "number" + readonly minimum?: number | "Infinity" | "-Infinity" | "NaN" + readonly maximum?: number | "Infinity" | "-Infinity" | "NaN" + readonly default?: number | "Infinity" | "-Infinity" | "NaN" + } + | { + readonly key: string + readonly title?: string + readonly description?: string + readonly required?: boolean + readonly when?: { readonly key: string; readonly op: "eq" | "neq"; readonly value: string } + readonly type: "integer" + readonly minimum?: number | "Infinity" | "-Infinity" | "NaN" + readonly maximum?: number | "Infinity" | "-Infinity" | "NaN" + readonly default?: number | "Infinity" | "-Infinity" | "NaN" + } + | { + readonly key: string + readonly title?: string + readonly description?: string + readonly required?: boolean + readonly when?: { readonly key: string; readonly op: "eq" | "neq"; readonly value: string } + readonly type: "boolean" + readonly default?: boolean + } + | { + readonly key: string + readonly title?: string + readonly description?: string + readonly required?: boolean + readonly when?: { readonly key: string; readonly op: "eq" | "neq"; readonly value: string } + readonly type: "multiselect" + readonly options: ReadonlyArray<{ + readonly value: string + readonly label: string + readonly description?: string + }> + readonly minItems?: number + readonly maxItems?: number + readonly custom?: boolean + readonly default?: ReadonlyArray + } + > | null + readonly url?: string | null + }["mode"] + readonly fields?: { + readonly id?: string | null + readonly title?: string + readonly metadata?: { readonly [x: string]: JsonValue } + readonly mode: "form" | "url" + readonly fields?: ReadonlyArray< + | { + readonly key: string + readonly title?: string + readonly description?: string + readonly required?: boolean + readonly when?: { readonly key: string; readonly op: "eq" | "neq"; readonly value: string } + readonly type: "string" + readonly format?: "email" | "uri" | "date" | "date-time" + readonly minLength?: number + readonly maxLength?: number + readonly pattern?: string + readonly placeholder?: string + readonly default?: string + readonly options?: ReadonlyArray<{ + readonly value: string + readonly label: string + readonly description?: string + }> + readonly custom?: boolean + } + | { + readonly key: string + readonly title?: string + readonly description?: string + readonly required?: boolean + readonly when?: { readonly key: string; readonly op: "eq" | "neq"; readonly value: string } + readonly type: "number" + readonly minimum?: number | "Infinity" | "-Infinity" | "NaN" + readonly maximum?: number | "Infinity" | "-Infinity" | "NaN" + readonly default?: number | "Infinity" | "-Infinity" | "NaN" + } + | { + readonly key: string + readonly title?: string + readonly description?: string + readonly required?: boolean + readonly when?: { readonly key: string; readonly op: "eq" | "neq"; readonly value: string } + readonly type: "integer" + readonly minimum?: number | "Infinity" | "-Infinity" | "NaN" + readonly maximum?: number | "Infinity" | "-Infinity" | "NaN" + readonly default?: number | "Infinity" | "-Infinity" | "NaN" + } + | { + readonly key: string + readonly title?: string + readonly description?: string + readonly required?: boolean + readonly when?: { readonly key: string; readonly op: "eq" | "neq"; readonly value: string } + readonly type: "boolean" + readonly default?: boolean + } + | { + readonly key: string + readonly title?: string + readonly description?: string + readonly required?: boolean + readonly when?: { readonly key: string; readonly op: "eq" | "neq"; readonly value: string } + readonly type: "multiselect" + readonly options: ReadonlyArray<{ + readonly value: string + readonly label: string + readonly description?: string + }> + readonly minItems?: number + readonly maxItems?: number + readonly custom?: boolean + readonly default?: ReadonlyArray + } + > | null + readonly url?: string | null + }["fields"] + readonly url?: { + readonly id?: string | null + readonly title?: string + readonly metadata?: { readonly [x: string]: JsonValue } + readonly mode: "form" | "url" + readonly fields?: ReadonlyArray< + | { + readonly key: string + readonly title?: string + readonly description?: string + readonly required?: boolean + readonly when?: { readonly key: string; readonly op: "eq" | "neq"; readonly value: string } + readonly type: "string" + readonly format?: "email" | "uri" | "date" | "date-time" + readonly minLength?: number + readonly maxLength?: number + readonly pattern?: string + readonly placeholder?: string + readonly default?: string + readonly options?: ReadonlyArray<{ + readonly value: string + readonly label: string + readonly description?: string + }> + readonly custom?: boolean + } + | { + readonly key: string + readonly title?: string + readonly description?: string + readonly required?: boolean + readonly when?: { readonly key: string; readonly op: "eq" | "neq"; readonly value: string } + readonly type: "number" + readonly minimum?: number | "Infinity" | "-Infinity" | "NaN" + readonly maximum?: number | "Infinity" | "-Infinity" | "NaN" + readonly default?: number | "Infinity" | "-Infinity" | "NaN" + } + | { + readonly key: string + readonly title?: string + readonly description?: string + readonly required?: boolean + readonly when?: { readonly key: string; readonly op: "eq" | "neq"; readonly value: string } + readonly type: "integer" + readonly minimum?: number | "Infinity" | "-Infinity" | "NaN" + readonly maximum?: number | "Infinity" | "-Infinity" | "NaN" + readonly default?: number | "Infinity" | "-Infinity" | "NaN" + } + | { + readonly key: string + readonly title?: string + readonly description?: string + readonly required?: boolean + readonly when?: { readonly key: string; readonly op: "eq" | "neq"; readonly value: string } + readonly type: "boolean" + readonly default?: boolean + } + | { + readonly key: string + readonly title?: string + readonly description?: string + readonly required?: boolean + readonly when?: { readonly key: string; readonly op: "eq" | "neq"; readonly value: string } + readonly type: "multiselect" + readonly options: ReadonlyArray<{ + readonly value: string + readonly label: string + readonly description?: string + }> + readonly minItems?: number + readonly maxItems?: number + readonly custom?: boolean + readonly default?: ReadonlyArray + } + > | null + readonly url?: string | null + }["url"] +} + +export type FormCreateOutput = { + readonly data: + | { + readonly id: string + readonly sessionID: string + readonly title?: string + readonly metadata?: { readonly [x: string]: JsonValue } + readonly mode: "form" + readonly fields: ReadonlyArray< + | { + readonly key: string + readonly title?: string + readonly description?: string + readonly required?: boolean + readonly when?: { readonly key: string; readonly op: "eq" | "neq"; readonly value: string } + readonly type: "string" + readonly format?: "email" | "uri" | "date" | "date-time" + readonly minLength?: number + readonly maxLength?: number + readonly pattern?: string + readonly placeholder?: string + readonly default?: string + readonly options?: ReadonlyArray<{ + readonly value: string + readonly label: string + readonly description?: string + }> + readonly custom?: boolean + } + | { + readonly key: string + readonly title?: string + readonly description?: string + readonly required?: boolean + readonly when?: { readonly key: string; readonly op: "eq" | "neq"; readonly value: string } + readonly type: "number" + readonly minimum?: number | "Infinity" | "-Infinity" | "NaN" + readonly maximum?: number | "Infinity" | "-Infinity" | "NaN" + readonly default?: number | "Infinity" | "-Infinity" | "NaN" + } + | { + readonly key: string + readonly title?: string + readonly description?: string + readonly required?: boolean + readonly when?: { readonly key: string; readonly op: "eq" | "neq"; readonly value: string } + readonly type: "integer" + readonly minimum?: number | "Infinity" | "-Infinity" | "NaN" + readonly maximum?: number | "Infinity" | "-Infinity" | "NaN" + readonly default?: number | "Infinity" | "-Infinity" | "NaN" + } + | { + readonly key: string + readonly title?: string + readonly description?: string + readonly required?: boolean + readonly when?: { readonly key: string; readonly op: "eq" | "neq"; readonly value: string } + readonly type: "boolean" + readonly default?: boolean + } + | { + readonly key: string + readonly title?: string + readonly description?: string + readonly required?: boolean + readonly when?: { readonly key: string; readonly op: "eq" | "neq"; readonly value: string } + readonly type: "multiselect" + readonly options: ReadonlyArray<{ + readonly value: string + readonly label: string + readonly description?: string + }> + readonly minItems?: number + readonly maxItems?: number + readonly custom?: boolean + readonly default?: ReadonlyArray + } + > + } + | { + readonly id: string + readonly sessionID: string + readonly title?: string + readonly metadata?: { readonly [x: string]: JsonValue } + readonly mode: "url" + readonly url: string + } +}["data"] + +export type FormGetInput = { + readonly sessionID: { readonly sessionID: string; readonly formID: string }["sessionID"] + readonly formID: { readonly sessionID: string; readonly formID: string }["formID"] +} + +export type FormGetOutput = { + readonly data: + | { + readonly id: string + readonly sessionID: string + readonly title?: string + readonly metadata?: { readonly [x: string]: JsonValue } + readonly mode: "form" + readonly fields: ReadonlyArray< + | { + readonly key: string + readonly title?: string + readonly description?: string + readonly required?: boolean + readonly when?: { readonly key: string; readonly op: "eq" | "neq"; readonly value: string } + readonly type: "string" + readonly format?: "email" | "uri" | "date" | "date-time" + readonly minLength?: number + readonly maxLength?: number + readonly pattern?: string + readonly placeholder?: string + readonly default?: string + readonly options?: ReadonlyArray<{ + readonly value: string + readonly label: string + readonly description?: string + }> + readonly custom?: boolean + } + | { + readonly key: string + readonly title?: string + readonly description?: string + readonly required?: boolean + readonly when?: { readonly key: string; readonly op: "eq" | "neq"; readonly value: string } + readonly type: "number" + readonly minimum?: number | "Infinity" | "-Infinity" | "NaN" + readonly maximum?: number | "Infinity" | "-Infinity" | "NaN" + readonly default?: number | "Infinity" | "-Infinity" | "NaN" + } + | { + readonly key: string + readonly title?: string + readonly description?: string + readonly required?: boolean + readonly when?: { readonly key: string; readonly op: "eq" | "neq"; readonly value: string } + readonly type: "integer" + readonly minimum?: number | "Infinity" | "-Infinity" | "NaN" + readonly maximum?: number | "Infinity" | "-Infinity" | "NaN" + readonly default?: number | "Infinity" | "-Infinity" | "NaN" + } + | { + readonly key: string + readonly title?: string + readonly description?: string + readonly required?: boolean + readonly when?: { readonly key: string; readonly op: "eq" | "neq"; readonly value: string } + readonly type: "boolean" + readonly default?: boolean + } + | { + readonly key: string + readonly title?: string + readonly description?: string + readonly required?: boolean + readonly when?: { readonly key: string; readonly op: "eq" | "neq"; readonly value: string } + readonly type: "multiselect" + readonly options: ReadonlyArray<{ + readonly value: string + readonly label: string + readonly description?: string + }> + readonly minItems?: number + readonly maxItems?: number + readonly custom?: boolean + readonly default?: ReadonlyArray + } + > + } + | { + readonly id: string + readonly sessionID: string + readonly title?: string + readonly metadata?: { readonly [x: string]: JsonValue } + readonly mode: "url" + readonly url: string + } +}["data"] + +export type FormStateInput = { + readonly sessionID: { readonly sessionID: string; readonly formID: string }["sessionID"] + readonly formID: { readonly sessionID: string; readonly formID: string }["formID"] +} + +export type FormStateOutput = { + readonly data: + | { readonly status: "pending" } + | { + readonly status: "answered" + readonly answer: { readonly [x: string]: string | number | boolean | ReadonlyArray } + } + | { readonly status: "cancelled" } +}["data"] + +export type FormReplyInput = { + readonly sessionID: { readonly sessionID: string; readonly formID: string }["sessionID"] + readonly formID: { readonly sessionID: string; readonly formID: string }["formID"] + readonly answer: { + readonly answer: { readonly [x: string]: string | number | boolean | ReadonlyArray } + }["answer"] +} + +export type FormReplyOutput = void + +export type FormCancelInput = { + readonly sessionID: { readonly sessionID: string; readonly formID: string }["sessionID"] + readonly formID: { readonly sessionID: string; readonly formID: string }["formID"] +} + +export type FormCancelOutput = void + export type PermissionListRequestsInput = { readonly location?: { readonly location?: { readonly directory?: string | undefined; readonly workspace?: string | undefined } | undefined diff --git a/packages/core/src/location-services.ts b/packages/core/src/location-services.ts index 4a3e29bd867..d3150668fe2 100644 --- a/packages/core/src/location-services.ts +++ b/packages/core/src/location-services.ts @@ -10,6 +10,7 @@ import { FileMutation } from "./file-mutation" import { FileSystem } from "./filesystem" import { FileSystemSearch } from "./filesystem/search" import { Generate } from "./generate" +import { Form } from "./form" import { Watcher } from "./filesystem/watcher" import { Image } from "./image" import { Integration } from "./integration" @@ -83,6 +84,7 @@ export const locationServices = LayerNode.group([ ReferenceGuidance.node, SessionTodo.node, SessionContextEntry.node, + Form.node, QuestionV2.node, Generate.node, ReadToolFileSystem.node, diff --git a/packages/opencode/test/server/httpapi-exercise/index.ts b/packages/opencode/test/server/httpapi-exercise/index.ts index 2b768bc1d51..e737d971885 100644 --- a/packages/opencode/test/server/httpapi-exercise/index.ts +++ b/packages/opencode/test/server/httpapi-exercise/index.ts @@ -816,6 +816,78 @@ const scenarios: Scenario[] = [ object(body.location) array(body.data) }), + http.protected.get("/api/form/request", "v2.form.request.list").json(200, (body) => { + object(body) + object(body.location) + array(body.data) + }), + http.protected + .get("/api/session/{sessionID}/form", "v2.session.form.list") + .seeded((ctx) => ctx.session({ title: "Form list owner" })) + .at((ctx) => ({ + path: route("/api/session/{sessionID}/form", { sessionID: ctx.state.id }), + headers: ctx.headers(), + })) + .json(200, data(array)), + http.protected + .post("/api/session/{sessionID}/form", "v2.session.form.create") + .mutating() + .seeded((ctx) => ctx.session({ title: "Form create owner" })) + .at((ctx) => ({ + path: route("/api/session/{sessionID}/form", { sessionID: ctx.state.id }), + headers: ctx.headers(), + body: { mode: "url", url: "https://example.com/form" }, + })) + .json(200, (body) => { + object(body) + object(body.data) + check(typeof body.data.id === "string", "form create should return an ID") + check(body.data.mode === "url", "form create should preserve URL mode") + }), + http.protected + .get("/api/session/{sessionID}/form/{formID}", "v2.session.form.get") + .seeded((ctx) => ctx.session({ title: "Form get owner" })) + .at((ctx) => ({ + path: route("/api/session/{sessionID}/form/{formID}", { sessionID: ctx.state.id, formID: "frm_httpapi_missing" }), + headers: ctx.headers(), + })) + .json(404, object, "status"), + http.protected + .get("/api/session/{sessionID}/form/{formID}/state", "v2.session.form.state") + .seeded((ctx) => ctx.session({ title: "Form state owner" })) + .at((ctx) => ({ + path: route("/api/session/{sessionID}/form/{formID}/state", { + sessionID: ctx.state.id, + formID: "frm_httpapi_missing", + }), + headers: ctx.headers(), + })) + .json(404, object, "status"), + http.protected + .post("/api/session/{sessionID}/form/{formID}/reply", "v2.session.form.reply") + .mutating() + .seeded((ctx) => ctx.session({ title: "Form reply owner" })) + .at((ctx) => ({ + path: route("/api/session/{sessionID}/form/{formID}/reply", { + sessionID: ctx.state.id, + formID: "frm_httpapi_missing", + }), + headers: ctx.headers(), + body: { answer: {} }, + })) + .json(404, object, "status"), + http.protected + .post("/api/session/{sessionID}/form/{formID}/cancel", "v2.session.form.cancel") + .mutating() + .seeded((ctx) => ctx.session({ title: "Form cancel owner" })) + .at((ctx) => ({ + path: route("/api/session/{sessionID}/form/{formID}/cancel", { + sessionID: ctx.state.id, + formID: "frm_httpapi_missing", + }), + headers: ctx.headers(), + })) + .json(404, object, "status"), http.protected .post("/api/session/{sessionID}/permission", "v2.session.permission.create") .seeded((ctx) => ctx.session({ title: "Permission create owner" })) diff --git a/packages/plugin/src/v2/effect/generated/api.ts b/packages/plugin/src/v2/effect/generated/api.ts index 4994651c8cc..f027e0c436f 100644 --- a/packages/plugin/src/v2/effect/generated/api.ts +++ b/packages/plugin/src/v2/effect/generated/api.ts @@ -458,71 +458,137 @@ export interface ProjectApi { readonly directories: ProjectDirectoriesOperation } -type Endpoint13_0Request = Parameters[0] +type Endpoint13_0Request = Parameters[0] export type Endpoint13_0Input = { readonly location?: Endpoint13_0Request["query"]["location"] } -export type Endpoint13_0Output = EffectValue> -export type PermissionListRequestsOperation = ( - input?: Endpoint13_0Input, -) => Effect.Effect +export type Endpoint13_0Output = EffectValue> +export type FormListRequestsOperation = (input?: Endpoint13_0Input) => Effect.Effect -type Endpoint13_1Request = Parameters[0] -export type Endpoint13_1Input = { readonly projectID?: Endpoint13_1Request["query"]["projectID"] } -export type Endpoint13_1Output = EffectValue< +type Endpoint13_1Request = Parameters[0] +export type Endpoint13_1Input = { readonly sessionID: Endpoint13_1Request["params"]["sessionID"] } +export type Endpoint13_1Output = EffectValue>["data"] +export type FormListOperation = (input: Endpoint13_1Input) => Effect.Effect + +type Endpoint13_2Request = Parameters[0] +export type Endpoint13_2Input = { + readonly sessionID: Endpoint13_2Request["params"]["sessionID"] + readonly id?: Endpoint13_2Request["payload"]["id"] + readonly title?: Endpoint13_2Request["payload"]["title"] + readonly metadata?: Endpoint13_2Request["payload"]["metadata"] + readonly mode: Endpoint13_2Request["payload"]["mode"] + readonly fields?: Endpoint13_2Request["payload"]["fields"] + readonly url?: Endpoint13_2Request["payload"]["url"] +} +export type Endpoint13_2Output = EffectValue>["data"] +export type FormCreateOperation = (input: Endpoint13_2Input) => Effect.Effect + +type Endpoint13_3Request = Parameters[0] +export type Endpoint13_3Input = { + readonly sessionID: Endpoint13_3Request["params"]["sessionID"] + readonly formID: Endpoint13_3Request["params"]["formID"] +} +export type Endpoint13_3Output = EffectValue>["data"] +export type FormGetOperation = (input: Endpoint13_3Input) => Effect.Effect + +type Endpoint13_4Request = Parameters[0] +export type Endpoint13_4Input = { + readonly sessionID: Endpoint13_4Request["params"]["sessionID"] + readonly formID: Endpoint13_4Request["params"]["formID"] +} +export type Endpoint13_4Output = EffectValue>["data"] +export type FormStateOperation = (input: Endpoint13_4Input) => Effect.Effect + +type Endpoint13_5Request = Parameters[0] +export type Endpoint13_5Input = { + readonly sessionID: Endpoint13_5Request["params"]["sessionID"] + readonly formID: Endpoint13_5Request["params"]["formID"] + readonly answer: Endpoint13_5Request["payload"]["answer"] +} +export type Endpoint13_5Output = EffectValue> +export type FormReplyOperation = (input: Endpoint13_5Input) => Effect.Effect + +type Endpoint13_6Request = Parameters[0] +export type Endpoint13_6Input = { + readonly sessionID: Endpoint13_6Request["params"]["sessionID"] + readonly formID: Endpoint13_6Request["params"]["formID"] +} +export type Endpoint13_6Output = EffectValue> +export type FormCancelOperation = (input: Endpoint13_6Input) => Effect.Effect + +export interface FormApi { + readonly listRequests: FormListRequestsOperation + readonly list: FormListOperation + readonly create: FormCreateOperation + readonly get: FormGetOperation + readonly state: FormStateOperation + readonly reply: FormReplyOperation + readonly cancel: FormCancelOperation +} + +type Endpoint14_0Request = Parameters[0] +export type Endpoint14_0Input = { readonly location?: Endpoint14_0Request["query"]["location"] } +export type Endpoint14_0Output = EffectValue> +export type PermissionListRequestsOperation = ( + input?: Endpoint14_0Input, +) => Effect.Effect + +type Endpoint14_1Request = Parameters[0] +export type Endpoint14_1Input = { readonly projectID?: Endpoint14_1Request["query"]["projectID"] } +export type Endpoint14_1Output = EffectValue< ReturnType >["data"] export type PermissionListSavedOperation = ( - input?: Endpoint13_1Input, -) => Effect.Effect + input?: Endpoint14_1Input, +) => Effect.Effect -type Endpoint13_2Request = Parameters[0] -export type Endpoint13_2Input = { readonly id: Endpoint13_2Request["params"]["id"] } -export type Endpoint13_2Output = EffectValue> +type Endpoint14_2Request = Parameters[0] +export type Endpoint14_2Input = { readonly id: Endpoint14_2Request["params"]["id"] } +export type Endpoint14_2Output = EffectValue> export type PermissionRemoveSavedOperation = ( - input: Endpoint13_2Input, -) => Effect.Effect + input: Endpoint14_2Input, +) => Effect.Effect -type Endpoint13_3Request = Parameters[0] -export type Endpoint13_3Input = { - readonly sessionID: Endpoint13_3Request["params"]["sessionID"] - readonly id?: Endpoint13_3Request["payload"]["id"] - readonly action: Endpoint13_3Request["payload"]["action"] - readonly resources: Endpoint13_3Request["payload"]["resources"] - readonly save?: Endpoint13_3Request["payload"]["save"] - readonly metadata?: Endpoint13_3Request["payload"]["metadata"] - readonly source?: Endpoint13_3Request["payload"]["source"] - readonly agent?: Endpoint13_3Request["payload"]["agent"] +type Endpoint14_3Request = Parameters[0] +export type Endpoint14_3Input = { + readonly sessionID: Endpoint14_3Request["params"]["sessionID"] + readonly id?: Endpoint14_3Request["payload"]["id"] + readonly action: Endpoint14_3Request["payload"]["action"] + readonly resources: Endpoint14_3Request["payload"]["resources"] + readonly save?: Endpoint14_3Request["payload"]["save"] + readonly metadata?: Endpoint14_3Request["payload"]["metadata"] + readonly source?: Endpoint14_3Request["payload"]["source"] + readonly agent?: Endpoint14_3Request["payload"]["agent"] } -export type Endpoint13_3Output = EffectValue< +export type Endpoint14_3Output = EffectValue< ReturnType >["data"] -export type PermissionCreateOperation = (input: Endpoint13_3Input) => Effect.Effect +export type PermissionCreateOperation = (input: Endpoint14_3Input) => Effect.Effect -type Endpoint13_4Request = Parameters[0] -export type Endpoint13_4Input = { readonly sessionID: Endpoint13_4Request["params"]["sessionID"] } -export type Endpoint13_4Output = EffectValue< +type Endpoint14_4Request = Parameters[0] +export type Endpoint14_4Input = { readonly sessionID: Endpoint14_4Request["params"]["sessionID"] } +export type Endpoint14_4Output = EffectValue< ReturnType >["data"] -export type PermissionListOperation = (input: Endpoint13_4Input) => Effect.Effect +export type PermissionListOperation = (input: Endpoint14_4Input) => Effect.Effect -type Endpoint13_5Request = Parameters[0] -export type Endpoint13_5Input = { - readonly sessionID: Endpoint13_5Request["params"]["sessionID"] - readonly requestID: Endpoint13_5Request["params"]["requestID"] +type Endpoint14_5Request = Parameters[0] +export type Endpoint14_5Input = { + readonly sessionID: Endpoint14_5Request["params"]["sessionID"] + readonly requestID: Endpoint14_5Request["params"]["requestID"] } -export type Endpoint13_5Output = EffectValue< +export type Endpoint14_5Output = EffectValue< ReturnType >["data"] -export type PermissionGetOperation = (input: Endpoint13_5Input) => Effect.Effect +export type PermissionGetOperation = (input: Endpoint14_5Input) => Effect.Effect -type Endpoint13_6Request = Parameters[0] -export type Endpoint13_6Input = { - readonly sessionID: Endpoint13_6Request["params"]["sessionID"] - readonly requestID: Endpoint13_6Request["params"]["requestID"] - readonly reply: Endpoint13_6Request["payload"]["reply"] - readonly message?: Endpoint13_6Request["payload"]["message"] +type Endpoint14_6Request = Parameters[0] +export type Endpoint14_6Input = { + readonly sessionID: Endpoint14_6Request["params"]["sessionID"] + readonly requestID: Endpoint14_6Request["params"]["requestID"] + readonly reply: Endpoint14_6Request["payload"]["reply"] + readonly message?: Endpoint14_6Request["payload"]["message"] } -export type Endpoint13_6Output = EffectValue> -export type PermissionReplyOperation = (input: Endpoint13_6Input) => Effect.Effect +export type Endpoint14_6Output = EffectValue> +export type PermissionReplyOperation = (input: Endpoint14_6Input) => Effect.Effect export interface PermissionApi { readonly listRequests: PermissionListRequestsOperation @@ -534,100 +600,100 @@ export interface PermissionApi { readonly reply: PermissionReplyOperation } -type Endpoint14_0Request = Parameters[0] -export type Endpoint14_0Input = { - readonly location?: Endpoint14_0Request["query"]["location"] - readonly path?: Endpoint14_0Request["query"]["path"] +type Endpoint15_0Request = Parameters[0] +export type Endpoint15_0Input = { + readonly location?: Endpoint15_0Request["query"]["location"] + readonly path?: Endpoint15_0Request["query"]["path"] } -export type Endpoint14_0Output = EffectValue> -export type FileListOperation = (input?: Endpoint14_0Input) => Effect.Effect +export type Endpoint15_0Output = EffectValue> +export type FileListOperation = (input?: Endpoint15_0Input) => Effect.Effect -type Endpoint14_1Request = Parameters[0] -export type Endpoint14_1Input = { - readonly location?: Endpoint14_1Request["query"]["location"] - readonly query: Endpoint14_1Request["query"]["query"] - readonly type?: Endpoint14_1Request["query"]["type"] - readonly limit?: Endpoint14_1Request["query"]["limit"] +type Endpoint15_1Request = Parameters[0] +export type Endpoint15_1Input = { + readonly location?: Endpoint15_1Request["query"]["location"] + readonly query: Endpoint15_1Request["query"]["query"] + readonly type?: Endpoint15_1Request["query"]["type"] + readonly limit?: Endpoint15_1Request["query"]["limit"] } -export type Endpoint14_1Output = EffectValue> -export type FileFindOperation = (input: Endpoint14_1Input) => Effect.Effect +export type Endpoint15_1Output = EffectValue> +export type FileFindOperation = (input: Endpoint15_1Input) => Effect.Effect export interface FileApi { readonly list: FileListOperation readonly find: FileFindOperation } -type Endpoint15_0Request = Parameters[0] -export type Endpoint15_0Input = { readonly location?: Endpoint15_0Request["query"]["location"] } -export type Endpoint15_0Output = EffectValue> -export type CommandListOperation = (input?: Endpoint15_0Input) => Effect.Effect +type Endpoint16_0Request = Parameters[0] +export type Endpoint16_0Input = { readonly location?: Endpoint16_0Request["query"]["location"] } +export type Endpoint16_0Output = EffectValue> +export type CommandListOperation = (input?: Endpoint16_0Input) => Effect.Effect export interface CommandApi { readonly list: CommandListOperation } -type Endpoint16_0Request = Parameters[0] -export type Endpoint16_0Input = { readonly location?: Endpoint16_0Request["query"]["location"] } -export type Endpoint16_0Output = EffectValue> -export type SkillListOperation = (input?: Endpoint16_0Input) => Effect.Effect +type Endpoint17_0Request = Parameters[0] +export type Endpoint17_0Input = { readonly location?: Endpoint17_0Request["query"]["location"] } +export type Endpoint17_0Output = EffectValue> +export type SkillListOperation = (input?: Endpoint17_0Input) => Effect.Effect export interface SkillApi { readonly list: SkillListOperation } -export type Endpoint17_0Output = StreamValue>> -export type EventSubscribeOperation = () => Stream.Stream +export type Endpoint18_0Output = StreamValue>> +export type EventSubscribeOperation = () => Stream.Stream -export type Endpoint17_1Output = StreamValue>> -export type EventChangesOperation = () => Stream.Stream +export type Endpoint18_1Output = StreamValue>> +export type EventChangesOperation = () => Stream.Stream export interface EventApi { readonly subscribe: EventSubscribeOperation readonly changes: EventChangesOperation } -type Endpoint18_0Request = Parameters[0] -export type Endpoint18_0Input = { readonly location?: Endpoint18_0Request["query"]["location"] } -export type Endpoint18_0Output = EffectValue> -export type PtyListOperation = (input?: Endpoint18_0Input) => Effect.Effect +type Endpoint19_0Request = Parameters[0] +export type Endpoint19_0Input = { readonly location?: Endpoint19_0Request["query"]["location"] } +export type Endpoint19_0Output = EffectValue> +export type PtyListOperation = (input?: Endpoint19_0Input) => Effect.Effect -type Endpoint18_1Request = Parameters[0] -export type Endpoint18_1Input = { - readonly location?: Endpoint18_1Request["query"]["location"] - readonly command?: Endpoint18_1Request["payload"]["command"] - readonly args?: Endpoint18_1Request["payload"]["args"] - readonly cwd?: Endpoint18_1Request["payload"]["cwd"] - readonly title?: Endpoint18_1Request["payload"]["title"] - readonly env?: Endpoint18_1Request["payload"]["env"] +type Endpoint19_1Request = Parameters[0] +export type Endpoint19_1Input = { + readonly location?: Endpoint19_1Request["query"]["location"] + readonly command?: Endpoint19_1Request["payload"]["command"] + readonly args?: Endpoint19_1Request["payload"]["args"] + readonly cwd?: Endpoint19_1Request["payload"]["cwd"] + readonly title?: Endpoint19_1Request["payload"]["title"] + readonly env?: Endpoint19_1Request["payload"]["env"] } -export type Endpoint18_1Output = EffectValue> -export type PtyCreateOperation = (input?: Endpoint18_1Input) => Effect.Effect +export type Endpoint19_1Output = EffectValue> +export type PtyCreateOperation = (input?: Endpoint19_1Input) => Effect.Effect -type Endpoint18_2Request = Parameters[0] -export type Endpoint18_2Input = { - readonly ptyID: Endpoint18_2Request["params"]["ptyID"] - readonly location?: Endpoint18_2Request["query"]["location"] +type Endpoint19_2Request = Parameters[0] +export type Endpoint19_2Input = { + readonly ptyID: Endpoint19_2Request["params"]["ptyID"] + readonly location?: Endpoint19_2Request["query"]["location"] } -export type Endpoint18_2Output = EffectValue> -export type PtyGetOperation = (input: Endpoint18_2Input) => Effect.Effect +export type Endpoint19_2Output = EffectValue> +export type PtyGetOperation = (input: Endpoint19_2Input) => Effect.Effect -type Endpoint18_3Request = Parameters[0] -export type Endpoint18_3Input = { - readonly ptyID: Endpoint18_3Request["params"]["ptyID"] - readonly location?: Endpoint18_3Request["query"]["location"] - readonly title?: Endpoint18_3Request["payload"]["title"] - readonly size?: Endpoint18_3Request["payload"]["size"] +type Endpoint19_3Request = Parameters[0] +export type Endpoint19_3Input = { + readonly ptyID: Endpoint19_3Request["params"]["ptyID"] + readonly location?: Endpoint19_3Request["query"]["location"] + readonly title?: Endpoint19_3Request["payload"]["title"] + readonly size?: Endpoint19_3Request["payload"]["size"] } -export type Endpoint18_3Output = EffectValue> -export type PtyUpdateOperation = (input: Endpoint18_3Input) => Effect.Effect +export type Endpoint19_3Output = EffectValue> +export type PtyUpdateOperation = (input: Endpoint19_3Input) => Effect.Effect -type Endpoint18_4Request = Parameters[0] -export type Endpoint18_4Input = { - readonly ptyID: Endpoint18_4Request["params"]["ptyID"] - readonly location?: Endpoint18_4Request["query"]["location"] +type Endpoint19_4Request = Parameters[0] +export type Endpoint19_4Input = { + readonly ptyID: Endpoint19_4Request["params"]["ptyID"] + readonly location?: Endpoint19_4Request["query"]["location"] } -export type Endpoint18_4Output = EffectValue> -export type PtyRemoveOperation = (input: Endpoint18_4Input) => Effect.Effect +export type Endpoint19_4Output = EffectValue> +export type PtyRemoveOperation = (input: Endpoint19_4Input) => Effect.Effect export interface PtyApi { readonly list: PtyListOperation @@ -637,47 +703,47 @@ export interface PtyApi { readonly remove: PtyRemoveOperation } -type Endpoint19_0Request = Parameters[0] -export type Endpoint19_0Input = { readonly location?: Endpoint19_0Request["query"]["location"] } -export type Endpoint19_0Output = EffectValue> -export type ShellListOperation = (input?: Endpoint19_0Input) => Effect.Effect +type Endpoint20_0Request = Parameters[0] +export type Endpoint20_0Input = { readonly location?: Endpoint20_0Request["query"]["location"] } +export type Endpoint20_0Output = EffectValue> +export type ShellListOperation = (input?: Endpoint20_0Input) => Effect.Effect -type Endpoint19_1Request = Parameters[0] -export type Endpoint19_1Input = { - readonly location?: Endpoint19_1Request["query"]["location"] - readonly command: Endpoint19_1Request["payload"]["command"] - readonly cwd?: Endpoint19_1Request["payload"]["cwd"] - readonly timeout?: Endpoint19_1Request["payload"]["timeout"] - readonly metadata?: Endpoint19_1Request["payload"]["metadata"] +type Endpoint20_1Request = Parameters[0] +export type Endpoint20_1Input = { + readonly location?: Endpoint20_1Request["query"]["location"] + readonly command: Endpoint20_1Request["payload"]["command"] + readonly cwd?: Endpoint20_1Request["payload"]["cwd"] + readonly timeout?: Endpoint20_1Request["payload"]["timeout"] + readonly metadata?: Endpoint20_1Request["payload"]["metadata"] } -export type Endpoint19_1Output = EffectValue> -export type ShellCreateOperation = (input: Endpoint19_1Input) => Effect.Effect +export type Endpoint20_1Output = EffectValue> +export type ShellCreateOperation = (input: Endpoint20_1Input) => Effect.Effect -type Endpoint19_2Request = Parameters[0] -export type Endpoint19_2Input = { - readonly id: Endpoint19_2Request["params"]["id"] - readonly location?: Endpoint19_2Request["query"]["location"] +type Endpoint20_2Request = Parameters[0] +export type Endpoint20_2Input = { + readonly id: Endpoint20_2Request["params"]["id"] + readonly location?: Endpoint20_2Request["query"]["location"] } -export type Endpoint19_2Output = EffectValue> -export type ShellGetOperation = (input: Endpoint19_2Input) => Effect.Effect +export type Endpoint20_2Output = EffectValue> +export type ShellGetOperation = (input: Endpoint20_2Input) => Effect.Effect -type Endpoint19_3Request = Parameters[0] -export type Endpoint19_3Input = { - readonly id: Endpoint19_3Request["params"]["id"] - readonly location?: Endpoint19_3Request["query"]["location"] - readonly cursor?: Endpoint19_3Request["query"]["cursor"] - readonly limit?: Endpoint19_3Request["query"]["limit"] +type Endpoint20_3Request = Parameters[0] +export type Endpoint20_3Input = { + readonly id: Endpoint20_3Request["params"]["id"] + readonly location?: Endpoint20_3Request["query"]["location"] + readonly cursor?: Endpoint20_3Request["query"]["cursor"] + readonly limit?: Endpoint20_3Request["query"]["limit"] } -export type Endpoint19_3Output = EffectValue> -export type ShellOutputOperation = (input: Endpoint19_3Input) => Effect.Effect +export type Endpoint20_3Output = EffectValue> +export type ShellOutputOperation = (input: Endpoint20_3Input) => Effect.Effect -type Endpoint19_4Request = Parameters[0] -export type Endpoint19_4Input = { - readonly id: Endpoint19_4Request["params"]["id"] - readonly location?: Endpoint19_4Request["query"]["location"] +type Endpoint20_4Request = Parameters[0] +export type Endpoint20_4Input = { + readonly id: Endpoint20_4Request["params"]["id"] + readonly location?: Endpoint20_4Request["query"]["location"] } -export type Endpoint19_4Output = EffectValue> -export type ShellRemoveOperation = (input: Endpoint19_4Input) => Effect.Effect +export type Endpoint20_4Output = EffectValue> +export type ShellRemoveOperation = (input: Endpoint20_4Input) => Effect.Effect export interface ShellApi { readonly list: ShellListOperation @@ -687,34 +753,34 @@ export interface ShellApi { readonly remove: ShellRemoveOperation } -type Endpoint20_0Request = Parameters[0] -export type Endpoint20_0Input = { readonly location?: Endpoint20_0Request["query"]["location"] } -export type Endpoint20_0Output = EffectValue> +type Endpoint21_0Request = Parameters[0] +export type Endpoint21_0Input = { readonly location?: Endpoint21_0Request["query"]["location"] } +export type Endpoint21_0Output = EffectValue> export type QuestionListRequestsOperation = ( - input?: Endpoint20_0Input, -) => Effect.Effect + input?: Endpoint21_0Input, +) => Effect.Effect -type Endpoint20_1Request = Parameters[0] -export type Endpoint20_1Input = { readonly sessionID: Endpoint20_1Request["params"]["sessionID"] } -export type Endpoint20_1Output = EffectValue>["data"] -export type QuestionListOperation = (input: Endpoint20_1Input) => Effect.Effect +type Endpoint21_1Request = Parameters[0] +export type Endpoint21_1Input = { readonly sessionID: Endpoint21_1Request["params"]["sessionID"] } +export type Endpoint21_1Output = EffectValue>["data"] +export type QuestionListOperation = (input: Endpoint21_1Input) => Effect.Effect -type Endpoint20_2Request = Parameters[0] -export type Endpoint20_2Input = { - readonly sessionID: Endpoint20_2Request["params"]["sessionID"] - readonly requestID: Endpoint20_2Request["params"]["requestID"] - readonly answers: Endpoint20_2Request["payload"]["answers"] +type Endpoint21_2Request = Parameters[0] +export type Endpoint21_2Input = { + readonly sessionID: Endpoint21_2Request["params"]["sessionID"] + readonly requestID: Endpoint21_2Request["params"]["requestID"] + readonly answers: Endpoint21_2Request["payload"]["answers"] } -export type Endpoint20_2Output = EffectValue> -export type QuestionReplyOperation = (input: Endpoint20_2Input) => Effect.Effect +export type Endpoint21_2Output = EffectValue> +export type QuestionReplyOperation = (input: Endpoint21_2Input) => Effect.Effect -type Endpoint20_3Request = Parameters[0] -export type Endpoint20_3Input = { - readonly sessionID: Endpoint20_3Request["params"]["sessionID"] - readonly requestID: Endpoint20_3Request["params"]["requestID"] +type Endpoint21_3Request = Parameters[0] +export type Endpoint21_3Input = { + readonly sessionID: Endpoint21_3Request["params"]["sessionID"] + readonly requestID: Endpoint21_3Request["params"]["requestID"] } -export type Endpoint20_3Output = EffectValue> -export type QuestionRejectOperation = (input: Endpoint20_3Input) => Effect.Effect +export type Endpoint21_3Output = EffectValue> +export type QuestionRejectOperation = (input: Endpoint21_3Input) => Effect.Effect export interface QuestionApi { readonly listRequests: QuestionListRequestsOperation @@ -723,43 +789,43 @@ export interface QuestionApi { readonly reject: QuestionRejectOperation } -type Endpoint21_0Request = Parameters[0] -export type Endpoint21_0Input = { readonly location?: Endpoint21_0Request["query"]["location"] } -export type Endpoint21_0Output = EffectValue> -export type ReferenceListOperation = (input?: Endpoint21_0Input) => Effect.Effect +type Endpoint22_0Request = Parameters[0] +export type Endpoint22_0Input = { readonly location?: Endpoint22_0Request["query"]["location"] } +export type Endpoint22_0Output = EffectValue> +export type ReferenceListOperation = (input?: Endpoint22_0Input) => Effect.Effect export interface ReferenceApi { readonly list: ReferenceListOperation } -type Endpoint22_0Request = Parameters[0] -export type Endpoint22_0Input = { - readonly projectID: Endpoint22_0Request["params"]["projectID"] - readonly location?: Endpoint22_0Request["query"]["location"] - readonly strategy: Endpoint22_0Request["payload"]["strategy"] - readonly directory: Endpoint22_0Request["payload"]["directory"] - readonly name?: Endpoint22_0Request["payload"]["name"] +type Endpoint23_0Request = Parameters[0] +export type Endpoint23_0Input = { + readonly projectID: Endpoint23_0Request["params"]["projectID"] + readonly location?: Endpoint23_0Request["query"]["location"] + readonly strategy: Endpoint23_0Request["payload"]["strategy"] + readonly directory: Endpoint23_0Request["payload"]["directory"] + readonly name?: Endpoint23_0Request["payload"]["name"] } -export type Endpoint22_0Output = EffectValue> -export type ProjectCopyCreateOperation = (input: Endpoint22_0Input) => Effect.Effect +export type Endpoint23_0Output = EffectValue> +export type ProjectCopyCreateOperation = (input: Endpoint23_0Input) => Effect.Effect -type Endpoint22_1Request = Parameters[0] -export type Endpoint22_1Input = { - readonly projectID: Endpoint22_1Request["params"]["projectID"] - readonly location?: Endpoint22_1Request["query"]["location"] - readonly directory: Endpoint22_1Request["payload"]["directory"] - readonly force: Endpoint22_1Request["payload"]["force"] +type Endpoint23_1Request = Parameters[0] +export type Endpoint23_1Input = { + readonly projectID: Endpoint23_1Request["params"]["projectID"] + readonly location?: Endpoint23_1Request["query"]["location"] + readonly directory: Endpoint23_1Request["payload"]["directory"] + readonly force: Endpoint23_1Request["payload"]["force"] } -export type Endpoint22_1Output = EffectValue> -export type ProjectCopyRemoveOperation = (input: Endpoint22_1Input) => Effect.Effect +export type Endpoint23_1Output = EffectValue> +export type ProjectCopyRemoveOperation = (input: Endpoint23_1Input) => Effect.Effect -type Endpoint22_2Request = Parameters[0] -export type Endpoint22_2Input = { - readonly projectID: Endpoint22_2Request["params"]["projectID"] - readonly location?: Endpoint22_2Request["query"]["location"] +type Endpoint23_2Request = Parameters[0] +export type Endpoint23_2Input = { + readonly projectID: Endpoint23_2Request["params"]["projectID"] + readonly location?: Endpoint23_2Request["query"]["location"] } -export type Endpoint22_2Output = EffectValue> -export type ProjectCopyRefreshOperation = (input: Endpoint22_2Input) => Effect.Effect +export type Endpoint23_2Output = EffectValue> +export type ProjectCopyRefreshOperation = (input: Endpoint23_2Input) => Effect.Effect export interface ProjectCopyApi { readonly create: ProjectCopyCreateOperation @@ -781,6 +847,7 @@ export interface AppApi { readonly "server.mcp": ServerMcpApi readonly credential: CredentialApi readonly project: ProjectApi + readonly form: FormApi readonly permission: PermissionApi readonly file: FileApi readonly command: CommandApi diff --git a/packages/protocol/src/api.ts b/packages/protocol/src/api.ts index 886e81c602c..8cf6b21835c 100644 --- a/packages/protocol/src/api.ts +++ b/packages/protocol/src/api.ts @@ -8,6 +8,7 @@ import { ProviderGroup } from "./groups/provider.js" import { makeSessionGroup } from "./groups/session.js" import { makePermissionGroup } from "./groups/permission.js" import { FileSystemGroup } from "./groups/fs.js" +import { makeFormGroup } from "./groups/form.js" import { CommandGroup } from "./groups/command.js" import { SkillGroup } from "./groups/skill.js" import { EventGroup, makeEventGroup } from "./groups/event.js" @@ -59,6 +60,7 @@ type MixedMiddlewareGroups< | ReturnType< typeof makePermissionGroup > + | ReturnType> | ReturnType> type ApiGroups< @@ -119,6 +121,7 @@ const makeApiFromGroup = < .add(McpGroup.middleware(locationMiddleware)) .add(CredentialGroup.middleware(locationMiddleware)) .add(ProjectGroup.middleware(locationMiddleware)) + .add(makeFormGroup(locationMiddleware, sessionLocationMiddleware)) .add(makePermissionGroup(locationMiddleware, sessionLocationMiddleware)) .add(FileSystemGroup.middleware(locationMiddleware)) .add(CommandGroup.middleware(locationMiddleware)) diff --git a/packages/protocol/src/client.ts b/packages/protocol/src/client.ts index 0744b15e943..65d539038f7 100644 --- a/packages/protocol/src/client.ts +++ b/packages/protocol/src/client.ts @@ -39,6 +39,7 @@ export const groupNames = { "server.provider": "provider", "server.integration": "integration", "server.credential": "credential", + "server.form": "form", "server.permission": "permission", "server.fs": "file", "server.command": "command", @@ -68,6 +69,7 @@ export const endpointNames = { "permission.request.list": "listRequests", "permission.saved.list": "listSaved", "permission.saved.remove": "removeSaved", + "form.request.list": "listRequests", "question.request.list": "listRequests", } as const diff --git a/packages/protocol/src/errors.ts b/packages/protocol/src/errors.ts index fdd30834396..a21d3d86d25 100644 --- a/packages/protocol/src/errors.ts +++ b/packages/protocol/src/errors.ts @@ -131,6 +131,33 @@ export class QuestionNotFoundError extends Schema.TaggedErrorClass()( + "FormNotFoundError", + { + id: Schema.String, + message: Schema.String, + }, + { httpApiStatus: 404 }, +) {} + +export class FormAlreadySettledError extends Schema.TaggedErrorClass()( + "FormAlreadySettledError", + { + id: Schema.String, + message: Schema.String, + }, + { httpApiStatus: 409 }, +) {} + +export class FormInvalidAnswerError extends Schema.TaggedErrorClass()( + "FormInvalidAnswerError", + { + id: Schema.String, + message: Schema.String, + }, + { httpApiStatus: 400 }, +) {} + export class ForbiddenError extends Schema.TaggedErrorClass()( "ForbiddenError", { message: Schema.String }, diff --git a/packages/protocol/src/groups/form.ts b/packages/protocol/src/groups/form.ts new file mode 100644 index 00000000000..75e14d31535 --- /dev/null +++ b/packages/protocol/src/groups/form.ts @@ -0,0 +1,144 @@ +import { Form } from "@opencode-ai/schema/form" +import { Location } from "@opencode-ai/schema/location" +import { Session } from "@opencode-ai/schema/session" +import { Context, Schema } from "effect" +import { HttpApiEndpoint, HttpApiGroup, HttpApiMiddleware, HttpApiSchema, OpenApi } from "effect/unstable/httpapi" +import { + ConflictError, + FormAlreadySettledError, + FormInvalidAnswerError, + FormNotFoundError, + InvalidRequestError, + SessionNotFoundError, +} from "../errors.js" +import { LocationQuery, locationQueryOpenApi } from "./location.js" + +const CreatePayload = Schema.Struct({ + id: Form.ID.pipe(Schema.optional), + title: Form.FormInfo.fields.title, + metadata: Form.FormInfo.fields.metadata, + mode: Schema.Literals(["form", "url"]), + fields: Form.FormInfo.fields.fields.pipe(Schema.optional), + url: Form.UrlInfo.fields.url.pipe(Schema.optional), +}).annotate({ identifier: "Form.CreatePayload" }) + +export type CreatePayload = typeof CreatePayload.Type + +export const makeFormGroup = < + LocationId extends HttpApiMiddleware.AnyId, + LocationService, + SessionLocationId extends HttpApiMiddleware.AnyId, + SessionLocationService, +>( + locationMiddleware: Context.Key, + sessionLocationMiddleware: Context.Key, +) => + HttpApiGroup.make("server.form") + .add( + HttpApiEndpoint.get("form.request.list", "/api/form/request", { + query: LocationQuery, + success: Location.response(Schema.Array(Form.Info)), + }) + .annotateMerge(locationQueryOpenApi) + .annotateMerge( + OpenApi.annotations({ + identifier: "v2.form.request.list", + summary: "List pending form requests", + description: "Retrieve pending forms for a location.", + }), + ), + ) + .middleware(locationMiddleware) + .add( + HttpApiEndpoint.get("session.form.list", "/api/session/:sessionID/form", { + params: { sessionID: Session.ID }, + success: Schema.Struct({ data: Schema.Array(Form.Info) }), + error: SessionNotFoundError, + }) + .middleware(sessionLocationMiddleware) + .annotateMerge( + OpenApi.annotations({ + identifier: "v2.session.form.list", + summary: "List session forms", + description: "Retrieve pending forms for a session.", + }), + ), + ) + .add( + HttpApiEndpoint.post("session.form.create", "/api/session/:sessionID/form", { + params: { sessionID: Session.ID }, + payload: CreatePayload, + success: Schema.Struct({ data: Form.Info }), + error: [SessionNotFoundError, ConflictError, InvalidRequestError], + }) + .middleware(sessionLocationMiddleware) + .annotateMerge( + OpenApi.annotations({ + identifier: "v2.session.form.create", + summary: "Create session form", + description: "Create a form for a session.", + }), + ), + ) + .add( + HttpApiEndpoint.get("session.form.get", "/api/session/:sessionID/form/:formID", { + params: { sessionID: Session.ID, formID: Form.ID }, + success: Schema.Struct({ data: Form.Info }), + error: [SessionNotFoundError, FormNotFoundError], + }) + .middleware(sessionLocationMiddleware) + .annotateMerge( + OpenApi.annotations({ + identifier: "v2.session.form.get", + summary: "Get session form", + description: "Retrieve a form for a session.", + }), + ), + ) + .add( + HttpApiEndpoint.get("session.form.state", "/api/session/:sessionID/form/:formID/state", { + params: { sessionID: Session.ID, formID: Form.ID }, + success: Schema.Struct({ data: Form.State }), + error: [SessionNotFoundError, FormNotFoundError], + }) + .middleware(sessionLocationMiddleware) + .annotateMerge( + OpenApi.annotations({ + identifier: "v2.session.form.state", + summary: "Get form state", + description: "Retrieve the current state for a form.", + }), + ), + ) + .add( + HttpApiEndpoint.post("session.form.reply", "/api/session/:sessionID/form/:formID/reply", { + params: { sessionID: Session.ID, formID: Form.ID }, + payload: Form.Reply, + success: HttpApiSchema.NoContent, + error: [SessionNotFoundError, FormAlreadySettledError, FormInvalidAnswerError, FormNotFoundError], + }) + .middleware(sessionLocationMiddleware) + .annotateMerge( + OpenApi.annotations({ + identifier: "v2.session.form.reply", + summary: "Reply to form", + description: "Submit an answer to a pending form.", + }), + ), + ) + .add( + HttpApiEndpoint.post("session.form.cancel", "/api/session/:sessionID/form/:formID/cancel", { + params: { sessionID: Session.ID, formID: Form.ID }, + success: HttpApiSchema.NoContent, + error: [SessionNotFoundError, FormAlreadySettledError, FormNotFoundError], + }) + .middleware(sessionLocationMiddleware) + .annotateMerge( + OpenApi.annotations({ + identifier: "v2.session.form.cancel", + summary: "Cancel form", + description: "Cancel a pending form.", + }), + ), + ) + .annotateMerge(OpenApi.annotations({ title: "forms", description: "Session form routes." })) diff --git a/packages/sdk/js/src/v2/gen/sdk.gen.ts b/packages/sdk/js/src/v2/gen/sdk.gen.ts index bbc29d71acb..554c31dfb27 100644 --- a/packages/sdk/js/src/v2/gen/sdk.gen.ts +++ b/packages/sdk/js/src/v2/gen/sdk.gen.ts @@ -76,6 +76,8 @@ import type { FindTextResponses, FormatterStatusErrors, FormatterStatusResponses, + FormCreatePayload2, + FormReply2, GlobalConfigGetErrors, GlobalConfigGetResponses, GlobalConfigUpdateErrors, @@ -278,6 +280,8 @@ import type { V2EventChangesResponses, V2EventSubscribeErrors, V2EventSubscribeResponses, + V2FormRequestListErrors, + V2FormRequestListResponses, V2FsFindErrors, V2FsFindResponses, V2FsListErrors, @@ -370,6 +374,18 @@ import type { V2SessionCreateResponses, V2SessionForkErrors, V2SessionForkResponses, + V2SessionFormCancelErrors, + V2SessionFormCancelResponses, + V2SessionFormCreateErrors, + V2SessionFormCreateResponses, + V2SessionFormGetErrors, + V2SessionFormGetResponses, + V2SessionFormListErrors, + V2SessionFormListResponses, + V2SessionFormReplyErrors, + V2SessionFormReplyResponses, + V2SessionFormStateErrors, + V2SessionFormStateResponses, V2SessionGetErrors, V2SessionGetResponses, V2SessionInterruptErrors, @@ -5342,6 +5358,193 @@ export class Context extends HeyApiClient { } } +export class Form extends HeyApiClient { + /** + * List session forms + * + * Retrieve pending forms for a session. + */ + public list( + parameters: { + sessionID: string + }, + options?: Options, + ) { + const params = buildClientParams([parameters], [{ args: [{ in: "path", key: "sessionID" }] }]) + return (options?.client ?? this.client).get({ + url: "/api/session/{sessionID}/form", + ...options, + ...params, + }) + } + + /** + * Create session form + * + * Create a form for a session. + */ + public create( + parameters: { + sessionID: string + formCreatePayload: FormCreatePayload2 + }, + options?: Options, + ) { + const params = buildClientParams( + [parameters], + [ + { + args: [ + { in: "path", key: "sessionID" }, + { key: "formCreatePayload", map: "body" }, + ], + }, + ], + ) + return (options?.client ?? this.client).post( + { + url: "/api/session/{sessionID}/form", + ...options, + ...params, + headers: { + "Content-Type": "application/json", + ...options?.headers, + ...params.headers, + }, + }, + ) + } + + /** + * Get session form + * + * Retrieve a form for a session. + */ + public get( + parameters: { + sessionID: string + formID: string + }, + options?: Options, + ) { + const params = buildClientParams( + [parameters], + [ + { + args: [ + { in: "path", key: "sessionID" }, + { in: "path", key: "formID" }, + ], + }, + ], + ) + return (options?.client ?? this.client).get({ + url: "/api/session/{sessionID}/form/{formID}", + ...options, + ...params, + }) + } + + /** + * Get form state + * + * Retrieve the current state for a form. + */ + public state( + parameters: { + sessionID: string + formID: string + }, + options?: Options, + ) { + const params = buildClientParams( + [parameters], + [ + { + args: [ + { in: "path", key: "sessionID" }, + { in: "path", key: "formID" }, + ], + }, + ], + ) + return (options?.client ?? this.client).get({ + url: "/api/session/{sessionID}/form/{formID}/state", + ...options, + ...params, + }) + } + + /** + * Reply to form + * + * Submit an answer to a pending form. + */ + public reply( + parameters: { + sessionID: string + formID: string + formReply: FormReply2 + }, + options?: Options, + ) { + const params = buildClientParams( + [parameters], + [ + { + args: [ + { in: "path", key: "sessionID" }, + { in: "path", key: "formID" }, + { key: "formReply", map: "body" }, + ], + }, + ], + ) + return (options?.client ?? this.client).post({ + url: "/api/session/{sessionID}/form/{formID}/reply", + ...options, + ...params, + headers: { + "Content-Type": "application/json", + ...options?.headers, + ...params.headers, + }, + }) + } + + /** + * Cancel form + * + * Cancel a pending form. + */ + public cancel( + parameters: { + sessionID: string + formID: string + }, + options?: Options, + ) { + const params = buildClientParams( + [parameters], + [ + { + args: [ + { in: "path", key: "sessionID" }, + { in: "path", key: "formID" }, + ], + }, + ], + ) + return (options?.client ?? this.client).post( + { + url: "/api/session/{sessionID}/form/{formID}/cancel", + ...options, + ...params, + }, + ) + } +} + export class Permission2 extends HeyApiClient { /** * List session permission requests @@ -6235,6 +6438,11 @@ export class Session3 extends HeyApiClient { return (this._context ??= new Context({ client: this.client })) } + private _form?: Form + get form(): Form { + return (this._form ??= new Form({ client: this.client })) + } + private _permission?: Permission2 get permission(): Permission2 { return (this._permission ??= new Permission2({ client: this.client })) @@ -6839,6 +7047,37 @@ export class Project2 extends HeyApiClient { } export class Request extends HeyApiClient { + /** + * List pending form requests + * + * Retrieve pending forms for a location. + */ + public list( + parameters?: { + location?: { + directory?: string | null + workspace?: string | null + } | null + }, + options?: Options, + ) { + const params = buildClientParams([parameters], [{ args: [{ in: "query", key: "location" }] }]) + return (options?.client ?? this.client).get({ + url: "/api/form/request", + ...options, + ...params, + }) + } +} + +export class Form2 extends HeyApiClient { + private _request?: Request + get request(): Request { + return (this._request ??= new Request({ client: this.client })) + } +} + +export class Request2 extends HeyApiClient { /** * List pending permission requests * @@ -6915,9 +7154,9 @@ export class Saved extends HeyApiClient { } export class Permission3 extends HeyApiClient { - private _request?: Request - get request(): Request { - return (this._request ??= new Request({ client: this.client })) + private _request?: Request2 + get request(): Request2 { + return (this._request ??= new Request2({ client: this.client })) } private _saved?: Saved @@ -7519,7 +7758,7 @@ export class Shell extends HeyApiClient { } } -export class Request2 extends HeyApiClient { +export class Request3 extends HeyApiClient { /** * List pending question requests * @@ -7548,9 +7787,9 @@ export class Request2 extends HeyApiClient { } export class Question3 extends HeyApiClient { - private _request?: Request2 - get request(): Request2 { - return (this._request ??= new Request2({ client: this.client })) + private _request?: Request3 + get request(): Request3 { + return (this._request ??= new Request3({ client: this.client })) } } @@ -7755,6 +7994,11 @@ export class V2 extends HeyApiClient { return (this._project ??= new Project2({ client: this.client })) } + private _form?: Form2 + get form(): Form2 { + return (this._form ??= new Form2({ client: this.client })) + } + private _permission?: Permission3 get permission(): Permission3 { return (this._permission ??= new Permission3({ client: this.client })) diff --git a/packages/sdk/js/src/v2/gen/types.gen.ts b/packages/sdk/js/src/v2/gen/types.gen.ts index c1f22c8a81c..dd4c35a2e0b 100644 --- a/packages/sdk/js/src/v2/gen/types.gen.ts +++ b/packages/sdk/js/src/v2/gen/types.gen.ts @@ -77,6 +77,9 @@ export type Event = | EventQuestionV2Asked | EventQuestionV2Replied | EventQuestionV2Rejected + | EventFormCreated + | EventFormReplied + | EventFormCancelled | EventTodoUpdated | EventLspUpdated | EventPermissionAsked @@ -1475,6 +1478,30 @@ export type GlobalEvent = { requestID: string } } + | { + id: string + type: "form.created" + properties: { + form: FormFormInfo | FormUrlInfo + } + } + | { + id: string + type: "form.replied" + properties: { + id: string + sessionID: string + answer: FormAnswer + } + } + | { + id: string + type: "form.cancelled" + properties: { + id: string + sessionID: string + } + } | { id: string type: "todo.updated" @@ -2941,6 +2968,24 @@ export type ProviderNotFoundError = { message: string } +export type FormNotFoundError = { + _tag: "FormNotFoundError" + id: string + message: string +} + +export type FormAlreadySettledError = { + _tag: "FormAlreadySettledError" + id: string + message: string +} + +export type FormInvalidAnswerError = { + _tag: "FormInvalidAnswerError" + id: string + message: string +} + export type OutputFormat1 = | { type: "text" @@ -3097,6 +3142,9 @@ export type V2Event = | QuestionV2Asked | QuestionV2Replied | QuestionV2Rejected + | FormCreated + | FormReplied + | FormCancelled | TodoUpdated | LspUpdated | PermissionAsked @@ -3370,6 +3418,121 @@ export type QuestionV2Tool = { export type QuestionV2Answer = Array +export type FormMetadata = { + [key: string]: unknown +} + +export type FormWhen = { + key: string + op: "eq" | "neq" + value: string +} + +export type FormOption = { + value: string + label: string + description?: string +} + +export type FormStringField = { + key: string + title?: string + description?: string + required?: boolean + when?: FormWhen + type: "string" + format?: "email" | "uri" | "date" | "date-time" + minLength?: number + maxLength?: number + pattern?: string + placeholder?: string + default?: string + options?: Array + custom?: boolean +} + +export type FormNumberField = { + key: string + title?: string + description?: string + required?: boolean + when?: FormWhen + type: "number" + minimum?: number | "NaN" | "Infinity" | "-Infinity" | "Infinity" | "-Infinity" | "NaN" + maximum?: number | "NaN" | "Infinity" | "-Infinity" | "Infinity" | "-Infinity" | "NaN" + default?: number | "NaN" | "Infinity" | "-Infinity" | "Infinity" | "-Infinity" | "NaN" +} + +export type FormIntegerField = { + key: string + title?: string + description?: string + required?: boolean + when?: FormWhen + type: "integer" + minimum?: number | "NaN" | "Infinity" | "-Infinity" | "Infinity" | "-Infinity" | "NaN" + maximum?: number | "NaN" | "Infinity" | "-Infinity" | "Infinity" | "-Infinity" | "NaN" + default?: number | "NaN" | "Infinity" | "-Infinity" | "Infinity" | "-Infinity" | "NaN" +} + +export type FormBooleanField = { + key: string + title?: string + description?: string + required?: boolean + when?: FormWhen + type: "boolean" + default?: boolean +} + +export type FormMultiselectField = { + key: string + title?: string + description?: string + required?: boolean + when?: FormWhen + type: "multiselect" + options: Array + minItems?: number + maxItems?: number + custom?: boolean + default?: Array +} + +export type FormFormInfo = { + id: string + sessionID: string + title?: string + metadata?: FormMetadata + mode: "form" + fields: Array +} + +export type FormUrlInfo = { + id: string + sessionID: string + title?: string + metadata?: FormMetadata + mode: "url" + url: string +} + +export type FormValue = + | string + | number + | "NaN" + | "Infinity" + | "-Infinity" + | "Infinity" + | "-Infinity" + | "NaN" + | boolean + | Array + +export type FormAnswer = { + [key: string]: FormValue +} + export type ProjectVcs = "git" export type ProjectIcon = { @@ -5391,6 +5554,31 @@ export type ProjectCurrent = { directory: string } +export type FormCreatePayload = { + id?: string + title?: string + metadata?: FormMetadata + mode: "form" | "url" + fields?: Array + url?: string +} + +export type FormState = + | { + status: "pending" + } + | { + status: "answered" + answer: FormAnswer + } + | { + status: "cancelled" + } + +export type FormReply = { + answer: FormAnswer +} + export type PermissionV2Request = { id: string sessionID: string @@ -6194,6 +6382,86 @@ export type QuestionV2Rejected = { } } +export type FormNumberField1 = { + key: string + title?: string + description?: string + required?: boolean + when?: FormWhen + type: "number" + minimum?: number | "NaN" | "Infinity" | "-Infinity" + maximum?: number | "NaN" | "Infinity" | "-Infinity" + default?: number | "NaN" | "Infinity" | "-Infinity" +} + +export type FormIntegerField1 = { + key: string + title?: string + description?: string + required?: boolean + when?: FormWhen + type: "integer" + minimum?: number | "NaN" | "Infinity" | "-Infinity" + maximum?: number | "NaN" | "Infinity" | "-Infinity" + default?: number | "NaN" | "Infinity" | "-Infinity" +} + +export type FormCreated = { + id: string + metadata?: { + [key: string]: unknown + } + type: "form.created" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + form: FormFormInfo | FormUrlInfo + } +} + +export type FormValue1 = string | number | "NaN" | "Infinity" | "-Infinity" | boolean | Array + +export type FormReplied = { + id: string + metadata?: { + [key: string]: unknown + } + type: "form.replied" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + id: string + sessionID: string + answer: FormAnswer + } +} + +export type FormCancelled = { + id: string + metadata?: { + [key: string]: unknown + } + type: "form.cancelled" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef + data: { + id: string + sessionID: string + } +} + export type TodoUpdated = { id: string metadata?: { @@ -7505,6 +7773,57 @@ export type EventQuestionV2Rejected = { } } +export type FormNumberField2 = { + key: string + title?: string + description?: string + required?: boolean + when?: FormWhen + type: "number" + minimum?: number | "NaN" | "Infinity" | "-Infinity" + maximum?: number | "NaN" | "Infinity" | "-Infinity" + default?: number | "NaN" | "Infinity" | "-Infinity" +} + +export type FormIntegerField2 = { + key: string + title?: string + description?: string + required?: boolean + when?: FormWhen + type: "integer" + minimum?: number | "NaN" | "Infinity" | "-Infinity" + maximum?: number | "NaN" | "Infinity" | "-Infinity" + default?: number | "NaN" | "Infinity" | "-Infinity" +} + +export type EventFormCreated = { + id: string + type: "form.created" + properties: { + form: FormFormInfo | FormUrlInfo + } +} + +export type EventFormReplied = { + id: string + type: "form.replied" + properties: { + id: string + sessionID: string + answer: FormAnswer + } +} + +export type EventFormCancelled = { + id: string + type: "form.cancelled" + properties: { + id: string + sessionID: string + } +} + export type EventTodoUpdated = { id: string type: "todo.updated" @@ -9333,6 +9652,166 @@ export type ProjectDirectory2 = { export type ProjectDirectories2 = Array +export type FormMetadata2 = { + [key: string]: unknown +} + +export type FormWhen2 = { + key: string + op: "eq" | "neq" + value: string +} + +export type FormOption2 = { + value: string + label: string + description?: string +} + +export type FormStringField2 = { + key: string + title?: string + description?: string + required?: boolean + when?: FormWhen2 + type: "string" + format?: "email" | "uri" | "date" | "date-time" + minLength?: number + maxLength?: number + pattern?: string + placeholder?: string + default?: string + options?: Array + custom?: boolean +} + +export type FormNumberField3 = { + key: string + title?: string + description?: string + required?: boolean + when?: FormWhen2 + type: "number" + minimum?: number | "NaN" | "Infinity" | "-Infinity" | "Infinity" | "-Infinity" | "NaN" + maximum?: number | "NaN" | "Infinity" | "-Infinity" | "Infinity" | "-Infinity" | "NaN" + default?: number | "NaN" | "Infinity" | "-Infinity" | "Infinity" | "-Infinity" | "NaN" +} + +export type FormIntegerField3 = { + key: string + title?: string + description?: string + required?: boolean + when?: FormWhen2 + type: "integer" + minimum?: number | "NaN" | "Infinity" | "-Infinity" | "Infinity" | "-Infinity" | "NaN" + maximum?: number | "NaN" | "Infinity" | "-Infinity" | "Infinity" | "-Infinity" | "NaN" + default?: number | "NaN" | "Infinity" | "-Infinity" | "Infinity" | "-Infinity" | "NaN" +} + +export type FormBooleanField2 = { + key: string + title?: string + description?: string + required?: boolean + when?: FormWhen2 + type: "boolean" + default?: boolean +} + +export type FormMultiselectField2 = { + key: string + title?: string + description?: string + required?: boolean + when?: FormWhen2 + type: "multiselect" + options: Array + minItems?: number + maxItems?: number + custom?: boolean + default?: Array +} + +export type FormFormInfo2 = { + id: string + sessionID: string + title?: string + metadata?: FormMetadata2 + mode: "form" + fields: Array +} + +export type FormUrlInfo2 = { + id: string + sessionID: string + title?: string + metadata?: FormMetadata2 + mode: "url" + url: string +} + +export type FormCreatePayload2 = { + id?: string | null + title?: string + metadata?: FormMetadata2 + mode: "form" | "url" + fields?: Array< + FormStringField2 | FormNumberField3 | FormIntegerField3 | FormBooleanField2 | FormMultiselectField2 + > | null + url?: string | null +} + +export type FormNotFoundErrorV2 = { + _tag: "FormNotFoundError" + id: string + message: string +} + +export type FormValue2 = + | string + | number + | "NaN" + | "Infinity" + | "-Infinity" + | "Infinity" + | "-Infinity" + | "NaN" + | boolean + | Array + +export type FormAnswer2 = { + [key: string]: FormValue2 +} + +export type FormState2 = + | { + status: "pending" + } + | { + status: "answered" + answer: FormAnswer2 + } + | { + status: "cancelled" + } + +export type FormReply2 = { + answer: FormAnswer2 +} + +export type FormAlreadySettledErrorV2 = { + _tag: "FormAlreadySettledError" + id: string + message: string +} + +export type FormInvalidAnswerErrorV2 = { + _tag: "FormInvalidAnswerError" + id: string + message: string +} + export type PermissionV2Source2 = { type: "tool" messageID: string @@ -10619,6 +11098,112 @@ export type QuestionV2Rejected2 = { } } +export type FormMetadata1 = { + [key: string]: unknown +} + +export type FormNumberField12 = { + key: string + title?: string + description?: string + required?: boolean + when?: FormWhen2 + type: "number" + minimum?: number | "NaN" | "Infinity" | "-Infinity" + maximum?: number | "NaN" | "Infinity" | "-Infinity" + default?: number | "NaN" | "Infinity" | "-Infinity" +} + +export type FormIntegerField12 = { + key: string + title?: string + description?: string + required?: boolean + when?: FormWhen2 + type: "integer" + minimum?: number | "NaN" | "Infinity" | "-Infinity" + maximum?: number | "NaN" | "Infinity" | "-Infinity" + default?: number | "NaN" | "Infinity" | "-Infinity" +} + +export type FormFormInfo1 = { + id: string + sessionID: string + title?: string + metadata?: FormMetadata1 + mode: "form" + fields: Array +} + +export type FormUrlInfo1 = { + id: string + sessionID: string + title?: string + metadata?: FormMetadata1 + mode: "url" + url: string +} + +export type FormCreated2 = { + id: string + metadata?: { + [key: string]: unknown + } + type: "form.created" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef2 + data: { + form: FormFormInfo1 | FormUrlInfo1 + } +} + +export type FormValue12 = string | number | "NaN" | "Infinity" | "-Infinity" | boolean | Array + +export type FormAnswer1 = { + [key: string]: FormValue12 +} + +export type FormReplied2 = { + id: string + metadata?: { + [key: string]: unknown + } + type: "form.replied" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef2 + data: { + id: string + sessionID: string + answer: FormAnswer1 + } +} + +export type FormCancelled2 = { + id: string + metadata?: { + [key: string]: unknown + } + type: "form.cancelled" + durable?: { + aggregateID: string + seq: number + version: number + } + location?: LocationRef2 + data: { + id: string + sessionID: string + } +} + export type TodoV2 = { /** * Brief description of the task @@ -11131,6 +11716,9 @@ export type V2EventV2 = | QuestionV2Asked2 | QuestionV2Replied2 | QuestionV2Rejected2 + | FormCreated2 + | FormReplied2 + | FormCancelled2 | TodoUpdated2 | SessionStatusV22 | SessionIdle2 @@ -17268,6 +17856,277 @@ export type V2ProjectDirectoriesResponses = { export type V2ProjectDirectoriesResponse = V2ProjectDirectoriesResponses[keyof V2ProjectDirectoriesResponses] +export type V2FormRequestListData = { + body?: never + path?: never + query?: { + location?: { + directory?: string | null + workspace?: string | null + } | null + } + url: "/api/form/request" +} + +export type V2FormRequestListErrors = { + /** + * InvalidRequestError + */ + 400: InvalidRequestErrorV2 + /** + * UnauthorizedError + */ + 401: UnauthorizedErrorV2 +} + +export type V2FormRequestListError = V2FormRequestListErrors[keyof V2FormRequestListErrors] + +export type V2FormRequestListResponses = { + /** + * Success + */ + 200: { + location: LocationInfo2 + data: Array + } +} + +export type V2FormRequestListResponse = V2FormRequestListResponses[keyof V2FormRequestListResponses] + +export type V2SessionFormListData = { + body?: never + path: { + sessionID: string + } + query?: never + url: "/api/session/{sessionID}/form" +} + +export type V2SessionFormListErrors = { + /** + * InvalidRequestError + */ + 400: InvalidRequestErrorV2 + /** + * UnauthorizedError + */ + 401: UnauthorizedErrorV2 + /** + * SessionNotFoundError + */ + 404: SessionNotFoundErrorV2 +} + +export type V2SessionFormListError = V2SessionFormListErrors[keyof V2SessionFormListErrors] + +export type V2SessionFormListResponses = { + /** + * Success + */ + 200: { + data: Array + } +} + +export type V2SessionFormListResponse = V2SessionFormListResponses[keyof V2SessionFormListResponses] + +export type V2SessionFormCreateData = { + body: FormCreatePayload2 + path: { + sessionID: string + } + query?: never + url: "/api/session/{sessionID}/form" +} + +export type V2SessionFormCreateErrors = { + /** + * InvalidRequestError + */ + 400: InvalidRequestError1 | InvalidRequestErrorV2 + /** + * UnauthorizedError + */ + 401: UnauthorizedErrorV2 + /** + * SessionNotFoundError + */ + 404: SessionNotFoundErrorV2 + /** + * ConflictError + */ + 409: ConflictErrorV2 +} + +export type V2SessionFormCreateError = V2SessionFormCreateErrors[keyof V2SessionFormCreateErrors] + +export type V2SessionFormCreateResponses = { + /** + * Success + */ + 200: { + data: FormFormInfo2 | FormUrlInfo2 + } +} + +export type V2SessionFormCreateResponse = V2SessionFormCreateResponses[keyof V2SessionFormCreateResponses] + +export type V2SessionFormGetData = { + body?: never + path: { + sessionID: string + formID: string + } + query?: never + url: "/api/session/{sessionID}/form/{formID}" +} + +export type V2SessionFormGetErrors = { + /** + * InvalidRequestError + */ + 400: InvalidRequestErrorV2 + /** + * UnauthorizedError + */ + 401: UnauthorizedErrorV2 + /** + * SessionNotFoundError | FormNotFoundError + */ + 404: FormNotFoundErrorV2 | SessionNotFoundErrorV2 +} + +export type V2SessionFormGetError = V2SessionFormGetErrors[keyof V2SessionFormGetErrors] + +export type V2SessionFormGetResponses = { + /** + * Success + */ + 200: { + data: FormFormInfo2 | FormUrlInfo2 + } +} + +export type V2SessionFormGetResponse = V2SessionFormGetResponses[keyof V2SessionFormGetResponses] + +export type V2SessionFormStateData = { + body?: never + path: { + sessionID: string + formID: string + } + query?: never + url: "/api/session/{sessionID}/form/{formID}/state" +} + +export type V2SessionFormStateErrors = { + /** + * InvalidRequestError + */ + 400: InvalidRequestErrorV2 + /** + * UnauthorizedError + */ + 401: UnauthorizedErrorV2 + /** + * SessionNotFoundError | FormNotFoundError + */ + 404: FormNotFoundErrorV2 | SessionNotFoundErrorV2 +} + +export type V2SessionFormStateError = V2SessionFormStateErrors[keyof V2SessionFormStateErrors] + +export type V2SessionFormStateResponses = { + /** + * Success + */ + 200: { + data: FormState2 + } +} + +export type V2SessionFormStateResponse = V2SessionFormStateResponses[keyof V2SessionFormStateResponses] + +export type V2SessionFormReplyData = { + body: FormReply2 + path: { + sessionID: string + formID: string + } + query?: never + url: "/api/session/{sessionID}/form/{formID}/reply" +} + +export type V2SessionFormReplyErrors = { + /** + * FormInvalidAnswerError | InvalidRequestError + */ + 400: FormInvalidAnswerErrorV2 | InvalidRequestErrorV2 + /** + * UnauthorizedError + */ + 401: UnauthorizedErrorV2 + /** + * SessionNotFoundError | FormNotFoundError + */ + 404: FormNotFoundErrorV2 | SessionNotFoundErrorV2 + /** + * FormAlreadySettledError + */ + 409: FormAlreadySettledErrorV2 +} + +export type V2SessionFormReplyError = V2SessionFormReplyErrors[keyof V2SessionFormReplyErrors] + +export type V2SessionFormReplyResponses = { + /** + * + */ + 204: void +} + +export type V2SessionFormReplyResponse = V2SessionFormReplyResponses[keyof V2SessionFormReplyResponses] + +export type V2SessionFormCancelData = { + body?: never + path: { + sessionID: string + formID: string + } + query?: never + url: "/api/session/{sessionID}/form/{formID}/cancel" +} + +export type V2SessionFormCancelErrors = { + /** + * InvalidRequestError + */ + 400: InvalidRequestErrorV2 + /** + * UnauthorizedError + */ + 401: UnauthorizedErrorV2 + /** + * SessionNotFoundError | FormNotFoundError + */ + 404: FormNotFoundErrorV2 | SessionNotFoundErrorV2 + /** + * FormAlreadySettledError + */ + 409: FormAlreadySettledErrorV2 +} + +export type V2SessionFormCancelError = V2SessionFormCancelErrors[keyof V2SessionFormCancelErrors] + +export type V2SessionFormCancelResponses = { + /** + * + */ + 204: void +} + +export type V2SessionFormCancelResponse = V2SessionFormCancelResponses[keyof V2SessionFormCancelResponses] + export type V2PermissionRequestListData = { body?: never path?: never diff --git a/packages/server/src/handlers.ts b/packages/server/src/handlers.ts index 5ce5970a7a9..5a37247e99c 100644 --- a/packages/server/src/handlers.ts +++ b/packages/server/src/handlers.ts @@ -6,6 +6,7 @@ import { ProviderHandler } from "./handlers/provider" import { SessionHandler } from "./handlers/session" import { PermissionHandler } from "./handlers/permission" import { FileSystemHandler } from "./handlers/fs" +import { FormHandler } from "./handlers/form" import { CommandHandler } from "./handlers/command" import { SkillHandler } from "./handlers/skill" import { EventHandler } from "./handlers/event" @@ -37,6 +38,7 @@ export const handlers = Layer.mergeAll( McpHandler, CredentialHandler, ProjectHandler, + FormHandler, PermissionHandler, FileSystemHandler, CommandHandler, diff --git a/packages/server/src/handlers/form.ts b/packages/server/src/handlers/form.ts new file mode 100644 index 00000000000..9ffd1b93e1b --- /dev/null +++ b/packages/server/src/handlers/form.ts @@ -0,0 +1,123 @@ +import { Form } from "@opencode-ai/core/form" +import { + ConflictError, + FormAlreadySettledError, + FormInvalidAnswerError, + FormNotFoundError, + InvalidRequestError, +} from "@opencode-ai/protocol/errors" +import { Effect } from "effect" +import { HttpApiBuilder, HttpApiSchema } from "effect/unstable/httpapi" +import { Api } from "../api" +import { response } from "../location" + +function missingForm(id: Form.ID) { + return new FormNotFoundError({ id, message: `Form not found: ${id}` }) +} + +export const FormHandler = HttpApiBuilder.group(Api, "server.form", (handlers) => + Effect.gen(function* () { + const requireOwnedForm = Effect.fnUntraced(function* (sessionID: Form.Info["sessionID"], formID: Form.ID) { + const form = yield* Form.Service + const info = yield* form.get(formID).pipe(Effect.catchTag("Form.NotFoundError", () => missingForm(formID))) + if (info.sessionID !== sessionID) return yield* missingForm(formID) + return { form, info } + }) + + return handlers + .handle( + "form.request.list", + Effect.fn(function* () { + const form = yield* Form.Service + return yield* response(form.list()) + }), + ) + .handle( + "session.form.list", + Effect.fn(function* (ctx) { + const form = yield* Form.Service + const forms = yield* form.list({ sessionID: ctx.params.sessionID }) + return { data: forms } + }), + ) + .handle( + "session.form.create", + Effect.fn(function* (ctx) { + const form = yield* Form.Service + const common = { + id: ctx.payload.id, + sessionID: ctx.params.sessionID, + title: ctx.payload.title, + metadata: ctx.payload.metadata, + } + const input = yield* (() => { + if (ctx.payload.mode === "form") { + if (!ctx.payload.fields) { + return new InvalidRequestError({ message: "Form fields are required", field: "fields" }) + } + return Effect.succeed({ ...common, mode: "form" as const, fields: ctx.payload.fields }) + } + if (!ctx.payload.url) return new InvalidRequestError({ message: "Form URL is required", field: "url" }) + return Effect.succeed({ ...common, mode: "url" as const, url: ctx.payload.url }) + })() + + const created = yield* form + .create(input) + .pipe( + Effect.catchTag( + "Form.AlreadyExistsError", + (error) => new ConflictError({ resource: error.id, message: error.message }), + ), + ) + return { data: created } + }), + ) + .handle( + "session.form.get", + Effect.fn(function* (ctx) { + const owned = yield* requireOwnedForm(ctx.params.sessionID, ctx.params.formID) + return { data: owned.info } + }), + ) + .handle( + "session.form.state", + Effect.fn(function* (ctx) { + const owned = yield* requireOwnedForm(ctx.params.sessionID, ctx.params.formID) + const data = yield* owned.form + .state(ctx.params.formID) + .pipe(Effect.catchTag("Form.NotFoundError", () => missingForm(ctx.params.formID))) + return { data } + }), + ) + .handle( + "session.form.reply", + Effect.fn(function* (ctx) { + const owned = yield* requireOwnedForm(ctx.params.sessionID, ctx.params.formID) + yield* owned.form.reply({ id: ctx.params.formID, answer: ctx.payload.answer }).pipe( + Effect.catchTags({ + "Form.AlreadySettledError": (error) => + new FormAlreadySettledError({ id: error.id, message: error.message }), + "Form.InvalidAnswerError": (error) => + new FormInvalidAnswerError({ id: error.id, message: error.message }), + "Form.NotFoundError": () => missingForm(ctx.params.formID), + }), + ) + return HttpApiSchema.NoContent.make() + }), + ) + .handle( + "session.form.cancel", + Effect.fn(function* (ctx) { + const owned = yield* requireOwnedForm(ctx.params.sessionID, ctx.params.formID) + yield* owned.form.cancel(ctx.params.formID).pipe( + Effect.catchTags({ + "Form.AlreadySettledError": (error) => + new FormAlreadySettledError({ id: error.id, message: error.message }), + "Form.NotFoundError": () => missingForm(ctx.params.formID), + }), + ) + return HttpApiSchema.NoContent.make() + }), + ) + }), +)