@opencode-ai/protocol 0.0.0-next-14661

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/dist/api.d.ts +44 -0
  2. package/dist/api.js +61 -0
  3. package/dist/client.d.ts +69 -0
  4. package/dist/client.js +52 -0
  5. package/dist/errors.d.ts +97 -0
  6. package/dist/errors.js +74 -0
  7. package/dist/groups/agent.d.ts +91 -0
  8. package/dist/groups/agent.js +15 -0
  9. package/dist/groups/command.d.ts +51 -0
  10. package/dist/groups/command.js +20 -0
  11. package/dist/groups/credential.d.ts +23 -0
  12. package/dist/groups/credential.js +28 -0
  13. package/dist/groups/event.d.ts +16086 -0
  14. package/dist/groups/event.js +42 -0
  15. package/dist/groups/fs.d.ts +35 -0
  16. package/dist/groups/fs.js +51 -0
  17. package/dist/groups/generate.d.ts +32 -0
  18. package/dist/groups/generate.js +27 -0
  19. package/dist/groups/health.d.ts +5 -0
  20. package/dist/groups/health.js +9 -0
  21. package/dist/groups/integration.d.ts +105 -0
  22. package/dist/groups/integration.js +98 -0
  23. package/dist/groups/location.d.ts +16 -0
  24. package/dist/groups/location.js +32 -0
  25. package/dist/groups/mcp.d.ts +30 -0
  26. package/dist/groups/mcp.js +17 -0
  27. package/dist/groups/message.d.ts +409 -0
  28. package/dist/groups/message.js +37 -0
  29. package/dist/groups/model.d.ts +151 -0
  30. package/dist/groups/model.js +22 -0
  31. package/dist/groups/permission.d.ts +153 -0
  32. package/dist/groups/permission.js +99 -0
  33. package/dist/groups/plugin.d.ts +14 -0
  34. package/dist/groups/plugin.js +20 -0
  35. package/dist/groups/project-copy.d.ts +49 -0
  36. package/dist/groups/project-copy.js +44 -0
  37. package/dist/groups/project.d.ts +24 -0
  38. package/dist/groups/project.js +30 -0
  39. package/dist/groups/provider.d.ts +156 -0
  40. package/dist/groups/provider.js +34 -0
  41. package/dist/groups/pty.d.ts +145 -0
  42. package/dist/groups/pty.js +111 -0
  43. package/dist/groups/question.d.ts +92 -0
  44. package/dist/groups/question.js +56 -0
  45. package/dist/groups/reference.d.ts +13 -0
  46. package/dist/groups/reference.js +20 -0
  47. package/dist/groups/session.d.ts +8020 -0
  48. package/dist/groups/session.js +331 -0
  49. package/dist/groups/shell.d.ts +120 -0
  50. package/dist/groups/shell.js +65 -0
  51. package/dist/groups/skill.d.ts +19 -0
  52. package/dist/groups/skill.js +20 -0
  53. package/dist/middleware/authorization.d.ts +13 -0
  54. package/dist/middleware/authorization.js +6 -0
  55. package/dist/middleware/schema-error.d.ts +13 -0
  56. package/dist/middleware/schema-error.js +4 -0
  57. package/package.json +38 -0
@@ -0,0 +1,42 @@
1
+ import { Event } from "@opencode-ai/schema/event";
2
+ import { EventManifest } from "@opencode-ai/schema/event-manifest";
3
+ import { Location } from "@opencode-ai/schema/location";
4
+ import { Schema } from "effect";
5
+ import { HttpApiEndpoint, HttpApiGroup, HttpApiSchema, OpenApi } from "effect/unstable/httpapi";
6
+ const fields = {
7
+ id: Event.ID,
8
+ metadata: Schema.optional(Schema.Record(Schema.String, Schema.Unknown)),
9
+ durable: Schema.optional(Schema.Struct({ aggregateID: Schema.String, seq: Schema.Int, version: Schema.Int })),
10
+ location: Schema.optional(Location.Ref),
11
+ };
12
+ const schema = (definitions) => Schema.Union([
13
+ ...definitions,
14
+ ...(definitions.some((definition) => definition.type === "server.connected")
15
+ ? []
16
+ : [
17
+ Schema.Struct({
18
+ ...fields,
19
+ type: Schema.Literal("server.connected"),
20
+ data: Schema.Struct({}),
21
+ }).annotate({ identifier: "V2Event.server.connected" }),
22
+ ]),
23
+ ]).annotate({ identifier: "V2Event" });
24
+ const make = (definitions) => {
25
+ const EventSchema = schema(definitions);
26
+ return {
27
+ schema: EventSchema,
28
+ group: HttpApiGroup.make("server.event")
29
+ .add(HttpApiEndpoint.get("event.subscribe", "/api/event", {
30
+ success: HttpApiSchema.StreamSse({ data: EventSchema }),
31
+ }).annotateMerge(OpenApi.annotations({
32
+ identifier: "v2.event.subscribe",
33
+ summary: "Subscribe to events",
34
+ description: "Subscribe to native event payloads for the server.",
35
+ })))
36
+ .annotateMerge(OpenApi.annotations({ title: "events", description: "Experimental event stream route." })),
37
+ };
38
+ };
39
+ export const makeEventGroup = (definitions) => make(definitions).group;
40
+ const event = make(EventManifest.ServerDefinitions);
41
+ export const EventGroup = event.group;
42
+ export const OpenCodeEvent = event.schema;
@@ -0,0 +1,35 @@
1
+ import { Location } from "@opencode-ai/schema/location";
2
+ import { Schema } from "effect";
3
+ import { HttpApiEndpoint, HttpApiGroup } from "effect/unstable/httpapi";
4
+ export declare const FileSystemGroup: HttpApiGroup.HttpApiGroup<"server.fs", HttpApiEndpoint.HttpApiEndpoint<"fs.read", "GET", "/api/fs/read/*", HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.StringTree<Schema.Struct<{
5
+ readonly location: Schema.optional<Schema.Struct<{
6
+ readonly directory: Schema.optional<Schema.String>;
7
+ readonly workspace: Schema.optional<Schema.String>;
8
+ }>>;
9
+ }>>, HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.Json<Schema.Uint8Array>, HttpApiEndpoint.Json<never>, never, never> | HttpApiEndpoint.HttpApiEndpoint<"fs.list", "GET", "/api/fs/list", HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.StringTree<Schema.Struct<{
10
+ readonly path: Schema.optional<Schema.brand<Schema.String, "RelativePath">>;
11
+ readonly location: Schema.optional<Schema.Struct<{
12
+ readonly directory: Schema.optional<Schema.String>;
13
+ readonly workspace: Schema.optional<Schema.String>;
14
+ }>>;
15
+ }>>, HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.Json<Schema.Struct<{
16
+ readonly location: typeof Location.Info;
17
+ readonly data: Schema.$Array<Schema.Struct<{
18
+ readonly path: Schema.brand<Schema.String, "RelativePath">;
19
+ readonly type: Schema.Literals<readonly ["file", "directory"]>;
20
+ }>>;
21
+ }>>, HttpApiEndpoint.Json<never>, never, never> | HttpApiEndpoint.HttpApiEndpoint<"fs.find", "GET", "/api/fs/find", HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.StringTree<Schema.Struct<{
22
+ readonly query: Schema.String;
23
+ readonly type: Schema.decodeTo<Schema.optional<Schema.toType<Schema.Literals<readonly ["file", "directory"]>>>, Schema.optionalKey<Schema.Literals<readonly ["file", "directory"]>>, never, never>;
24
+ readonly limit: Schema.optional<Schema.compose<Schema.Int, Schema.NumberFromString>>;
25
+ readonly location: Schema.optional<Schema.Struct<{
26
+ readonly directory: Schema.optional<Schema.String>;
27
+ readonly workspace: Schema.optional<Schema.String>;
28
+ }>>;
29
+ }>>, HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.Json<Schema.Struct<{
30
+ readonly location: typeof Location.Info;
31
+ readonly data: Schema.$Array<Schema.Struct<{
32
+ readonly path: Schema.brand<Schema.String, "RelativePath">;
33
+ readonly type: Schema.Literals<readonly ["file", "directory"]>;
34
+ }>>;
35
+ }>>, HttpApiEndpoint.Json<never>, never, never>, false>;
@@ -0,0 +1,51 @@
1
+ import { FileSystem } from "@opencode-ai/schema/filesystem";
2
+ import { Location } from "@opencode-ai/schema/location";
3
+ import { PositiveInt, RelativePath } from "@opencode-ai/schema/schema";
4
+ import { Schema } from "effect";
5
+ import { HttpApiEndpoint, HttpApiGroup, HttpApiSchema, OpenApi } from "effect/unstable/httpapi";
6
+ import { LocationQuery, locationQueryOpenApi } from "./location.js";
7
+ const ListQuery = Schema.Struct({
8
+ ...LocationQuery.fields,
9
+ path: RelativePath.pipe(Schema.optional),
10
+ });
11
+ const FindQuery = Schema.Struct({
12
+ ...LocationQuery.fields,
13
+ query: FileSystem.FindInput.fields.query,
14
+ type: FileSystem.FindInput.fields.type,
15
+ limit: Schema.NumberFromString.pipe(Schema.decodeTo(PositiveInt), Schema.optional),
16
+ });
17
+ export const FileSystemGroup = HttpApiGroup.make("server.fs")
18
+ .add(HttpApiEndpoint.get("fs.read", "/api/fs/read/*", {
19
+ query: LocationQuery,
20
+ success: Schema.Uint8Array.pipe(HttpApiSchema.asUint8Array()),
21
+ })
22
+ .annotateMerge(locationQueryOpenApi)
23
+ .annotateMerge(OpenApi.annotations({
24
+ identifier: "v2.fs.read",
25
+ summary: "Read file",
26
+ description: "Serve one file relative to the requested location.",
27
+ })))
28
+ .add(HttpApiEndpoint.get("fs.list", "/api/fs/list", {
29
+ query: ListQuery,
30
+ success: Location.response(Schema.Array(FileSystem.Entry)),
31
+ })
32
+ .annotateMerge(locationQueryOpenApi)
33
+ .annotateMerge(OpenApi.annotations({
34
+ identifier: "v2.fs.list",
35
+ summary: "List directory",
36
+ description: "List direct children of one directory relative to the requested location.",
37
+ })))
38
+ .add(HttpApiEndpoint.get("fs.find", "/api/fs/find", {
39
+ query: FindQuery,
40
+ success: Location.response(Schema.Array(FileSystem.Entry)),
41
+ })
42
+ .annotateMerge(locationQueryOpenApi)
43
+ .annotateMerge(OpenApi.annotations({
44
+ identifier: "v2.fs.find",
45
+ summary: "Find files",
46
+ description: "Find recursively ranked filesystem entries relative to the requested location.",
47
+ })))
48
+ .annotateMerge(OpenApi.annotations({
49
+ title: "filesystem",
50
+ description: "Experimental location-scoped filesystem routes.",
51
+ }));
@@ -0,0 +1,32 @@
1
+ import { Schema } from "effect";
2
+ import { HttpApiEndpoint, HttpApiGroup } from "effect/unstable/httpapi";
3
+ import { InvalidRequestError, ServiceUnavailableError } from "../errors.js";
4
+ export declare const GenerateGroup: HttpApiGroup.HttpApiGroup<"server.generate", HttpApiEndpoint.HttpApiEndpoint<"generate.text", "POST", "/api/generate", HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.StringTree<Schema.Struct<{
5
+ readonly location: Schema.optional<Schema.Struct<{
6
+ readonly directory: Schema.optional<Schema.String>;
7
+ readonly workspace: Schema.optional<Schema.String>;
8
+ }>>;
9
+ }>>, HttpApiEndpoint.Json<Schema.Struct<{
10
+ readonly prompt: Schema.String;
11
+ readonly model: Schema.optional<Schema.Struct<{
12
+ readonly id: Schema.brand<Schema.String, "ModelV2.ID">;
13
+ readonly providerID: Schema.brand<Schema.String, "ProviderV2.ID"> & {
14
+ opencode: string & import("effect/Brand").Brand<"ProviderV2.ID">;
15
+ anthropic: string & import("effect/Brand").Brand<"ProviderV2.ID">;
16
+ openai: string & import("effect/Brand").Brand<"ProviderV2.ID">;
17
+ google: string & import("effect/Brand").Brand<"ProviderV2.ID">;
18
+ googleVertex: string & import("effect/Brand").Brand<"ProviderV2.ID">;
19
+ githubCopilot: string & import("effect/Brand").Brand<"ProviderV2.ID">;
20
+ amazonBedrock: string & import("effect/Brand").Brand<"ProviderV2.ID">;
21
+ azure: string & import("effect/Brand").Brand<"ProviderV2.ID">;
22
+ openrouter: string & import("effect/Brand").Brand<"ProviderV2.ID">;
23
+ mistral: string & import("effect/Brand").Brand<"ProviderV2.ID">;
24
+ gitlab: string & import("effect/Brand").Brand<"ProviderV2.ID">;
25
+ };
26
+ readonly variant: Schema.decodeTo<Schema.optional<Schema.toType<Schema.brand<Schema.String, "VariantID">>>, Schema.optionalKey<Schema.brand<Schema.String, "VariantID">>, never, never>;
27
+ }>>;
28
+ }>>, HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.Json<Schema.Struct<{
29
+ readonly data: Schema.Struct<{
30
+ readonly text: Schema.String;
31
+ }>;
32
+ }>>, HttpApiEndpoint.Json<typeof InvalidRequestError | typeof ServiceUnavailableError>, never, never>, false>;
@@ -0,0 +1,27 @@
1
+ import { Model } from "@opencode-ai/schema/model";
2
+ import { Schema } from "effect";
3
+ import { HttpApiEndpoint, HttpApiGroup, OpenApi } from "effect/unstable/httpapi";
4
+ import { InvalidRequestError, ServiceUnavailableError } from "../errors.js";
5
+ import { LocationQuery, locationQueryOpenApi } from "./location.js";
6
+ export const GenerateGroup = HttpApiGroup.make("server.generate")
7
+ .add(HttpApiEndpoint.post("generate.text", "/api/generate", {
8
+ query: LocationQuery,
9
+ payload: Schema.Struct({
10
+ prompt: Schema.String,
11
+ model: Model.Ref.pipe(Schema.optional),
12
+ }),
13
+ success: Schema.Struct({
14
+ data: Schema.Struct({ text: Schema.String }),
15
+ }).annotate({ identifier: "GenerateTextResponse" }),
16
+ error: [InvalidRequestError, ServiceUnavailableError],
17
+ })
18
+ .annotateMerge(locationQueryOpenApi)
19
+ .annotateMerge(OpenApi.annotations({
20
+ identifier: "v2.generate.text",
21
+ summary: "Generate text",
22
+ description: "Run one stateless model generation at the requested location and return the assistant text. Uses the location's default model when none is specified.",
23
+ })))
24
+ .annotateMerge(OpenApi.annotations({
25
+ title: "generate",
26
+ description: "Experimental one-shot generation routes.",
27
+ }));
@@ -0,0 +1,5 @@
1
+ import { Schema } from "effect";
2
+ import { HttpApiEndpoint, HttpApiGroup } from "effect/unstable/httpapi";
3
+ export declare const HealthGroup: HttpApiGroup.HttpApiGroup<"server.health", HttpApiEndpoint.HttpApiEndpoint<"health.get", "GET", "/api/health", HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.Json<Schema.Struct<{
4
+ readonly healthy: Schema.Literal<true>;
5
+ }>>, HttpApiEndpoint.Json<never>, never, never>, false>;
@@ -0,0 +1,9 @@
1
+ import { Schema } from "effect";
2
+ import { HttpApiEndpoint, HttpApiGroup, OpenApi } from "effect/unstable/httpapi";
3
+ export const HealthGroup = HttpApiGroup.make("server.health").add(HttpApiEndpoint.get("health.get", "/api/health", {
4
+ success: Schema.Struct({ healthy: Schema.Literal(true) }),
5
+ }).annotateMerge(OpenApi.annotations({
6
+ identifier: "v2.health.get",
7
+ summary: "Check server health",
8
+ description: "Check whether the API server is ready to accept requests.",
9
+ })));
@@ -0,0 +1,105 @@
1
+ import { Integration } from "@opencode-ai/schema/integration";
2
+ import { Location } from "@opencode-ai/schema/location";
3
+ import { Schema } from "effect";
4
+ import { HttpApiEndpoint, HttpApiGroup, HttpApiSchema } from "effect/unstable/httpapi";
5
+ import { InvalidRequestError } from "../errors.js";
6
+ export declare const IntegrationGroup: HttpApiGroup.HttpApiGroup<"server.integration", HttpApiEndpoint.HttpApiEndpoint<"integration.list", "GET", "/api/integration", HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.StringTree<Schema.Struct<{
7
+ readonly location: Schema.optional<Schema.Struct<{
8
+ readonly directory: Schema.optional<Schema.String>;
9
+ readonly workspace: Schema.optional<Schema.String>;
10
+ }>>;
11
+ }>>, HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.Json<Schema.Struct<{
12
+ readonly location: typeof Location.Info;
13
+ readonly data: Schema.$Array<typeof Integration.Info>;
14
+ }>>, HttpApiEndpoint.Json<never>, never, never> | HttpApiEndpoint.HttpApiEndpoint<"integration.get", "GET", "/api/integration/:integrationID", HttpApiEndpoint.StringTree<Schema.Struct<{
15
+ integrationID: Schema.brand<Schema.String, "Integration.ID">;
16
+ }>>, HttpApiEndpoint.StringTree<Schema.Struct<{
17
+ readonly location: Schema.optional<Schema.Struct<{
18
+ readonly directory: Schema.optional<Schema.String>;
19
+ readonly workspace: Schema.optional<Schema.String>;
20
+ }>>;
21
+ }>>, HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.Json<Schema.Struct<{
22
+ readonly location: typeof Location.Info;
23
+ readonly data: Schema.UndefinedOr<typeof Integration.Info>;
24
+ }>>, HttpApiEndpoint.Json<never>, never, never> | HttpApiEndpoint.HttpApiEndpoint<"integration.connect.key", "POST", "/api/integration/:integrationID/connect/key", HttpApiEndpoint.StringTree<Schema.Struct<{
25
+ integrationID: Schema.brand<Schema.String, "Integration.ID">;
26
+ }>>, HttpApiEndpoint.StringTree<Schema.Struct<{
27
+ readonly location: Schema.optional<Schema.Struct<{
28
+ readonly directory: Schema.optional<Schema.String>;
29
+ readonly workspace: Schema.optional<Schema.String>;
30
+ }>>;
31
+ }>>, HttpApiEndpoint.Json<Schema.Struct<{
32
+ readonly key: Schema.String;
33
+ readonly label: Schema.optional<Schema.String>;
34
+ }>>, HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.Json<HttpApiSchema.NoContent>, HttpApiEndpoint.Json<typeof InvalidRequestError>, never, never> | HttpApiEndpoint.HttpApiEndpoint<"integration.connect.oauth", "POST", "/api/integration/:integrationID/connect/oauth", HttpApiEndpoint.StringTree<Schema.Struct<{
35
+ integrationID: Schema.brand<Schema.String, "Integration.ID">;
36
+ }>>, HttpApiEndpoint.StringTree<Schema.Struct<{
37
+ readonly location: Schema.optional<Schema.Struct<{
38
+ readonly directory: Schema.optional<Schema.String>;
39
+ readonly workspace: Schema.optional<Schema.String>;
40
+ }>>;
41
+ }>>, HttpApiEndpoint.Json<Schema.Struct<{
42
+ readonly methodID: Schema.brand<Schema.String, "Integration.MethodID">;
43
+ readonly inputs: Schema.$Record<Schema.String, Schema.String>;
44
+ readonly label: Schema.optional<Schema.String>;
45
+ }>>, HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.Json<Schema.Struct<{
46
+ readonly location: typeof Location.Info;
47
+ readonly data: typeof Integration.Attempt;
48
+ }>>, HttpApiEndpoint.Json<typeof InvalidRequestError>, never, never> | HttpApiEndpoint.HttpApiEndpoint<"integration.attempt.status", "GET", "/api/integration/attempt/:attemptID", HttpApiEndpoint.StringTree<Schema.Struct<{
49
+ attemptID: Schema.brand<Schema.String, "Integration.AttemptID"> & {
50
+ create: () => string & import("effect/Brand").Brand<"Integration.AttemptID">;
51
+ };
52
+ }>>, HttpApiEndpoint.StringTree<Schema.Struct<{
53
+ readonly location: Schema.optional<Schema.Struct<{
54
+ readonly directory: Schema.optional<Schema.String>;
55
+ readonly workspace: Schema.optional<Schema.String>;
56
+ }>>;
57
+ }>>, HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.Json<Schema.Struct<{
58
+ readonly location: typeof Location.Info;
59
+ readonly data: Schema.Union<readonly [Schema.Struct<{
60
+ readonly status: Schema.Literal<"pending">;
61
+ readonly time: Schema.Struct<{
62
+ readonly created: Schema.Number;
63
+ readonly expires: Schema.Number;
64
+ }>;
65
+ }>, Schema.Struct<{
66
+ readonly status: Schema.Literal<"complete">;
67
+ readonly time: Schema.Struct<{
68
+ readonly created: Schema.Number;
69
+ readonly expires: Schema.Number;
70
+ }>;
71
+ }>, Schema.Struct<{
72
+ readonly status: Schema.Literal<"failed">;
73
+ readonly message: Schema.String;
74
+ readonly time: Schema.Struct<{
75
+ readonly created: Schema.Number;
76
+ readonly expires: Schema.Number;
77
+ }>;
78
+ }>, Schema.Struct<{
79
+ readonly status: Schema.Literal<"expired">;
80
+ readonly time: Schema.Struct<{
81
+ readonly created: Schema.Number;
82
+ readonly expires: Schema.Number;
83
+ }>;
84
+ }>]>;
85
+ }>>, HttpApiEndpoint.Json<never>, never, never> | HttpApiEndpoint.HttpApiEndpoint<"integration.attempt.complete", "POST", "/api/integration/attempt/:attemptID/complete", HttpApiEndpoint.StringTree<Schema.Struct<{
86
+ attemptID: Schema.brand<Schema.String, "Integration.AttemptID"> & {
87
+ create: () => string & import("effect/Brand").Brand<"Integration.AttemptID">;
88
+ };
89
+ }>>, HttpApiEndpoint.StringTree<Schema.Struct<{
90
+ readonly location: Schema.optional<Schema.Struct<{
91
+ readonly directory: Schema.optional<Schema.String>;
92
+ readonly workspace: Schema.optional<Schema.String>;
93
+ }>>;
94
+ }>>, HttpApiEndpoint.Json<Schema.Struct<{
95
+ readonly code: Schema.optional<Schema.String>;
96
+ }>>, HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.Json<HttpApiSchema.NoContent>, HttpApiEndpoint.Json<typeof InvalidRequestError>, never, never> | HttpApiEndpoint.HttpApiEndpoint<"integration.attempt.cancel", "DELETE", "/api/integration/attempt/:attemptID", HttpApiEndpoint.StringTree<Schema.Struct<{
97
+ attemptID: Schema.brand<Schema.String, "Integration.AttemptID"> & {
98
+ create: () => string & import("effect/Brand").Brand<"Integration.AttemptID">;
99
+ };
100
+ }>>, HttpApiEndpoint.StringTree<Schema.Struct<{
101
+ readonly location: Schema.optional<Schema.Struct<{
102
+ readonly directory: Schema.optional<Schema.String>;
103
+ readonly workspace: Schema.optional<Schema.String>;
104
+ }>>;
105
+ }>>, HttpApiEndpoint.Json<never>, HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.Json<HttpApiSchema.NoContent>, HttpApiEndpoint.Json<never>, never, never>, false>;
@@ -0,0 +1,98 @@
1
+ import { Integration } from "@opencode-ai/schema/integration";
2
+ import { Location } from "@opencode-ai/schema/location";
3
+ import { Schema } from "effect";
4
+ import { HttpApiEndpoint, HttpApiGroup, HttpApiSchema, OpenApi } from "effect/unstable/httpapi";
5
+ import { InvalidRequestError } from "../errors.js";
6
+ import { LocationQuery, locationQueryOpenApi } from "./location.js";
7
+ const Inputs = Schema.Record(Schema.String, Schema.String);
8
+ export const IntegrationGroup = HttpApiGroup.make("server.integration")
9
+ .add(HttpApiEndpoint.get("integration.list", "/api/integration", {
10
+ query: LocationQuery,
11
+ success: Location.response(Schema.Array(Integration.Info)),
12
+ })
13
+ .annotateMerge(locationQueryOpenApi)
14
+ .annotateMerge(OpenApi.annotations({
15
+ identifier: "v2.integration.list",
16
+ summary: "List integrations",
17
+ description: "Retrieve available integrations and their authentication methods.",
18
+ })))
19
+ .add(HttpApiEndpoint.get("integration.get", "/api/integration/:integrationID", {
20
+ params: { integrationID: Integration.ID },
21
+ query: LocationQuery,
22
+ success: Location.response(Schema.UndefinedOr(Integration.Info)),
23
+ })
24
+ .annotateMerge(locationQueryOpenApi)
25
+ .annotateMerge(OpenApi.annotations({
26
+ identifier: "v2.integration.get",
27
+ summary: "Get integration",
28
+ description: "Retrieve one integration and its authentication methods.",
29
+ })))
30
+ .add(HttpApiEndpoint.post("integration.connect.key", "/api/integration/:integrationID/connect/key", {
31
+ params: { integrationID: Integration.ID },
32
+ query: LocationQuery,
33
+ payload: Schema.Struct({
34
+ key: Schema.String,
35
+ label: Schema.optional(Schema.String),
36
+ }),
37
+ success: HttpApiSchema.NoContent,
38
+ error: InvalidRequestError,
39
+ })
40
+ .annotateMerge(locationQueryOpenApi)
41
+ .annotateMerge(OpenApi.annotations({
42
+ identifier: "v2.integration.connect.key",
43
+ summary: "Connect with key",
44
+ description: "Run a key authentication method and store the resulting credential.",
45
+ })))
46
+ .add(HttpApiEndpoint.post("integration.connect.oauth", "/api/integration/:integrationID/connect/oauth", {
47
+ params: { integrationID: Integration.ID },
48
+ query: LocationQuery,
49
+ payload: Schema.Struct({
50
+ methodID: Integration.MethodID,
51
+ inputs: Inputs,
52
+ label: Schema.optional(Schema.String),
53
+ }),
54
+ success: Location.response(Integration.Attempt),
55
+ error: InvalidRequestError,
56
+ })
57
+ .annotateMerge(locationQueryOpenApi)
58
+ .annotateMerge(OpenApi.annotations({
59
+ identifier: "v2.integration.connect.oauth",
60
+ summary: "Begin OAuth connection",
61
+ description: "Start an OAuth attempt and return the authorization details.",
62
+ })))
63
+ .add(HttpApiEndpoint.get("integration.attempt.status", "/api/integration/attempt/:attemptID", {
64
+ params: { attemptID: Integration.AttemptID },
65
+ query: LocationQuery,
66
+ success: Location.response(Integration.AttemptStatus),
67
+ })
68
+ .annotateMerge(locationQueryOpenApi)
69
+ .annotateMerge(OpenApi.annotations({
70
+ identifier: "v2.integration.attempt.status",
71
+ summary: "Get OAuth attempt status",
72
+ description: "Poll the current status of an OAuth attempt.",
73
+ })))
74
+ .add(HttpApiEndpoint.post("integration.attempt.complete", "/api/integration/attempt/:attemptID/complete", {
75
+ params: { attemptID: Integration.AttemptID },
76
+ query: LocationQuery,
77
+ payload: Schema.Struct({ code: Schema.optional(Schema.String) }),
78
+ success: HttpApiSchema.NoContent,
79
+ error: InvalidRequestError,
80
+ })
81
+ .annotateMerge(locationQueryOpenApi)
82
+ .annotateMerge(OpenApi.annotations({
83
+ identifier: "v2.integration.attempt.complete",
84
+ summary: "Complete OAuth connection",
85
+ description: "Complete a code-based OAuth attempt and store the resulting credential.",
86
+ })))
87
+ .add(HttpApiEndpoint.delete("integration.attempt.cancel", "/api/integration/attempt/:attemptID", {
88
+ params: { attemptID: Integration.AttemptID },
89
+ query: LocationQuery,
90
+ success: HttpApiSchema.NoContent,
91
+ })
92
+ .annotateMerge(locationQueryOpenApi)
93
+ .annotateMerge(OpenApi.annotations({
94
+ identifier: "v2.integration.attempt.cancel",
95
+ summary: "Cancel OAuth connection",
96
+ description: "Cancel an OAuth attempt and release its resources.",
97
+ })))
98
+ .annotateMerge(OpenApi.annotations({ title: "integrations", description: "Integration discovery and authentication routes." }));
@@ -0,0 +1,16 @@
1
+ import { Location } from "@opencode-ai/schema/location";
2
+ import { Schema } from "effect";
3
+ import { HttpApiEndpoint, HttpApiGroup } from "effect/unstable/httpapi";
4
+ export declare const LocationQuery: Schema.Struct<{
5
+ readonly location: Schema.optional<Schema.Struct<{
6
+ readonly directory: Schema.optional<Schema.String>;
7
+ readonly workspace: Schema.optional<Schema.String>;
8
+ }>>;
9
+ }>;
10
+ export declare const locationQueryOpenApi: import("effect/Context").Context<never>;
11
+ export declare const LocationGroup: HttpApiGroup.HttpApiGroup<"server.location", HttpApiEndpoint.HttpApiEndpoint<"location.get", "GET", "/api/location", HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.StringTree<Schema.Struct<{
12
+ readonly location: Schema.optional<Schema.Struct<{
13
+ readonly directory: Schema.optional<Schema.String>;
14
+ readonly workspace: Schema.optional<Schema.String>;
15
+ }>>;
16
+ }>>, HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.Json<typeof Location.Info>, HttpApiEndpoint.Json<never>, never, never>, false>;
@@ -0,0 +1,32 @@
1
+ import { Location } from "@opencode-ai/schema/location";
2
+ import { Schema } from "effect";
3
+ import { HttpApiEndpoint, HttpApiGroup, OpenApi } from "effect/unstable/httpapi";
4
+ export const LocationQuery = Schema.Struct({
5
+ location: Schema.optional(Schema.Struct({
6
+ directory: Schema.optional(Schema.String),
7
+ workspace: Schema.optional(Schema.String),
8
+ })),
9
+ }).annotate({ identifier: "LocationQuery" });
10
+ export const locationQueryOpenApi = OpenApi.annotations({
11
+ transform: (operation) => {
12
+ const parameters = operation.parameters;
13
+ if (!Array.isArray(parameters))
14
+ return operation;
15
+ return {
16
+ ...operation,
17
+ parameters: parameters.map((parameter) => parameter?.name === "location" && parameter?.in === "query"
18
+ ? { ...parameter, style: "deepObject", explode: true }
19
+ : parameter),
20
+ };
21
+ },
22
+ });
23
+ export const LocationGroup = HttpApiGroup.make("server.location").add(HttpApiEndpoint.get("location.get", "/api/location", {
24
+ query: LocationQuery,
25
+ success: Location.Info,
26
+ })
27
+ .annotateMerge(locationQueryOpenApi)
28
+ .annotateMerge(OpenApi.annotations({
29
+ identifier: "v2.location.get",
30
+ summary: "Get location",
31
+ description: "Resolve the requested location or the server default location.",
32
+ })));
@@ -0,0 +1,30 @@
1
+ import { Location } from "@opencode-ai/schema/location";
2
+ import { Schema } from "effect";
3
+ import { HttpApiEndpoint, HttpApiGroup } from "effect/unstable/httpapi";
4
+ export declare const McpGroup: HttpApiGroup.HttpApiGroup<"server.mcp", HttpApiEndpoint.HttpApiEndpoint<"mcp.list", "GET", "/api/mcp", HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.StringTree<Schema.Struct<{
5
+ readonly location: Schema.optional<Schema.Struct<{
6
+ readonly directory: Schema.optional<Schema.String>;
7
+ readonly workspace: Schema.optional<Schema.String>;
8
+ }>>;
9
+ }>>, HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.Json<Schema.Struct<{
10
+ readonly location: typeof Location.Info;
11
+ readonly data: Schema.$Array<Schema.Struct<{
12
+ readonly name: Schema.String;
13
+ readonly status: Schema.toTaggedUnion<"status", readonly [Schema.Struct<{
14
+ readonly status: Schema.Literal<"connected">;
15
+ }>, Schema.Struct<{
16
+ readonly status: Schema.Literal<"disconnected">;
17
+ }>, Schema.Struct<{
18
+ readonly status: Schema.Literal<"disabled">;
19
+ }>, Schema.Struct<{
20
+ readonly status: Schema.Literal<"failed">;
21
+ readonly error: Schema.String;
22
+ }>, Schema.Struct<{
23
+ readonly status: Schema.Literal<"needs_auth">;
24
+ }>, Schema.Struct<{
25
+ readonly status: Schema.Literal<"needs_client_registration">;
26
+ readonly error: Schema.String;
27
+ }>]>;
28
+ readonly integrationID: Schema.decodeTo<Schema.optional<Schema.toType<Schema.brand<Schema.String, "Integration.ID">>>, Schema.optionalKey<Schema.brand<Schema.String, "Integration.ID">>, never, never>;
29
+ }>>;
30
+ }>>, HttpApiEndpoint.Json<never>, never, never>, false>;
@@ -0,0 +1,17 @@
1
+ import { Mcp } from "@opencode-ai/schema/mcp";
2
+ import { Location } from "@opencode-ai/schema/location";
3
+ import { Schema } from "effect";
4
+ import { HttpApiEndpoint, HttpApiGroup, OpenApi } from "effect/unstable/httpapi";
5
+ import { LocationQuery, locationQueryOpenApi } from "./location.js";
6
+ export const McpGroup = HttpApiGroup.make("server.mcp")
7
+ .add(HttpApiEndpoint.get("mcp.list", "/api/mcp", {
8
+ query: LocationQuery,
9
+ success: Location.response(Schema.Array(Mcp.Server)),
10
+ })
11
+ .annotateMerge(locationQueryOpenApi)
12
+ .annotateMerge(OpenApi.annotations({
13
+ identifier: "v2.mcp.list",
14
+ summary: "List MCP servers",
15
+ description: "Retrieve configured MCP servers and their connection status.",
16
+ })))
17
+ .annotateMerge(OpenApi.annotations({ title: "mcp", description: "MCP server status routes." }));