@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,153 @@
1
+ import { Location } from "@opencode-ai/schema/location";
2
+ import { Context, Schema } from "effect";
3
+ import { HttpApiEndpoint, HttpApiGroup, HttpApiMiddleware, HttpApiSchema } from "effect/unstable/httpapi";
4
+ import { PermissionNotFoundError, SessionNotFoundError } from "../errors.js";
5
+ export declare const makePermissionGroup: <LocationId extends HttpApiMiddleware.AnyId, LocationService, SessionLocationId extends HttpApiMiddleware.AnyId, SessionLocationService>(locationMiddleware: Context.Key<LocationId, LocationService>, sessionLocationMiddleware: Context.Key<SessionLocationId, SessionLocationService>) => HttpApiGroup.HttpApiGroup<"server.permission", HttpApiEndpoint.HttpApiEndpoint<"permission.request.list", "GET", "/api/permission/request", HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.StringTree<Schema.Struct<{
6
+ readonly location: Schema.optional<Schema.Struct<{
7
+ readonly directory: Schema.optional<Schema.String>;
8
+ readonly workspace: Schema.optional<Schema.String>;
9
+ }>>;
10
+ }>>, HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.Json<Schema.Struct<{
11
+ readonly location: typeof Location.Info;
12
+ readonly data: Schema.$Array<Schema.Struct<{
13
+ readonly sessionID: Schema.brand<Schema.String, "SessionID"> & {
14
+ create: () => string & import("effect/Brand").Brand<"SessionID">;
15
+ descending: (id?: string) => string & import("effect/Brand").Brand<"SessionID">;
16
+ };
17
+ readonly action: Schema.String;
18
+ readonly resources: Schema.$Array<Schema.String>;
19
+ readonly save: Schema.decodeTo<Schema.optional<Schema.toType<Schema.$Array<Schema.String>>>, Schema.optionalKey<Schema.$Array<Schema.String>>, never, never>;
20
+ readonly metadata: Schema.decodeTo<Schema.optional<Schema.toType<Schema.$Record<Schema.String, Schema.Unknown>>>, Schema.optionalKey<Schema.$Record<Schema.String, Schema.Unknown>>, never, never>;
21
+ readonly source: Schema.decodeTo<Schema.optional<Schema.toType<Schema.Union<readonly [Schema.Struct<{
22
+ readonly type: Schema.Literal<"tool">;
23
+ readonly messageID: Schema.String;
24
+ readonly callID: Schema.String;
25
+ }>]>>>, Schema.optionalKey<Schema.Union<readonly [Schema.Struct<{
26
+ readonly type: Schema.Literal<"tool">;
27
+ readonly messageID: Schema.String;
28
+ readonly callID: Schema.String;
29
+ }>]>>, never, never>;
30
+ readonly id: Schema.brand<Schema.String, "PermissionV2.ID"> & {
31
+ create: (id?: string) => string & import("effect/Brand").Brand<"PermissionV2.ID">;
32
+ };
33
+ }>>;
34
+ }>>, HttpApiEndpoint.Json<never>, LocationId, HttpApiMiddleware.Requires<LocationId>> | HttpApiEndpoint.HttpApiEndpoint<"permission.saved.list", "GET", "/api/permission/saved", HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.StringTree<Schema.Struct<{
35
+ readonly projectID: Schema.optional<Schema.brand<Schema.String, "Project.ID"> & {
36
+ global: string & import("effect/Brand").Brand<"Project.ID">;
37
+ }>;
38
+ }>>, HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.Json<Schema.Struct<{
39
+ readonly data: Schema.$Array<Schema.Struct<{
40
+ readonly id: Schema.brand<Schema.String, "PermissionSaved.ID"> & {
41
+ create: () => string & import("effect/Brand").Brand<"PermissionSaved.ID">;
42
+ };
43
+ readonly projectID: Schema.brand<Schema.String, "Project.ID"> & {
44
+ global: string & import("effect/Brand").Brand<"Project.ID">;
45
+ };
46
+ readonly action: Schema.String;
47
+ readonly resource: Schema.String;
48
+ }>>;
49
+ }>>, HttpApiEndpoint.Json<never>, LocationId, HttpApiMiddleware.Requires<LocationId>> | HttpApiEndpoint.HttpApiEndpoint<"permission.saved.remove", "DELETE", "/api/permission/saved/:id", HttpApiEndpoint.StringTree<Schema.Struct<{
50
+ id: Schema.brand<Schema.String, "PermissionSaved.ID"> & {
51
+ create: () => string & import("effect/Brand").Brand<"PermissionSaved.ID">;
52
+ };
53
+ }>>, HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.Json<never>, HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.Json<HttpApiSchema.NoContent>, HttpApiEndpoint.Json<never>, LocationId, HttpApiMiddleware.Requires<LocationId>> | HttpApiEndpoint.HttpApiEndpoint<"session.permission.create", "POST", "/api/session/:sessionID/permission", HttpApiEndpoint.StringTree<Schema.Struct<{
54
+ sessionID: Schema.brand<Schema.String, "SessionID"> & {
55
+ create: () => string & import("effect/Brand").Brand<"SessionID">;
56
+ descending: (id?: string) => string & import("effect/Brand").Brand<"SessionID">;
57
+ };
58
+ }>>, HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.Json<Schema.Struct<{
59
+ readonly id: Schema.optional<Schema.brand<Schema.String, "PermissionV2.ID"> & {
60
+ create: (id?: string) => string & import("effect/Brand").Brand<"PermissionV2.ID">;
61
+ }>;
62
+ readonly action: Schema.String;
63
+ readonly resources: Schema.$Array<Schema.String>;
64
+ readonly save: Schema.decodeTo<Schema.optional<Schema.toType<Schema.$Array<Schema.String>>>, Schema.optionalKey<Schema.$Array<Schema.String>>, never, never>;
65
+ readonly metadata: Schema.decodeTo<Schema.optional<Schema.toType<Schema.$Record<Schema.String, Schema.Unknown>>>, Schema.optionalKey<Schema.$Record<Schema.String, Schema.Unknown>>, never, never>;
66
+ readonly source: Schema.decodeTo<Schema.optional<Schema.toType<Schema.Union<readonly [Schema.Struct<{
67
+ readonly type: Schema.Literal<"tool">;
68
+ readonly messageID: Schema.String;
69
+ readonly callID: Schema.String;
70
+ }>]>>>, Schema.optionalKey<Schema.Union<readonly [Schema.Struct<{
71
+ readonly type: Schema.Literal<"tool">;
72
+ readonly messageID: Schema.String;
73
+ readonly callID: Schema.String;
74
+ }>]>>, never, never>;
75
+ readonly agent: Schema.optional<Schema.brand<Schema.String, "AgentV2.ID">>;
76
+ }>>, HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.Json<Schema.Struct<{
77
+ readonly data: Schema.Struct<{
78
+ readonly id: Schema.brand<Schema.String, "PermissionV2.ID"> & {
79
+ create: (id?: string) => string & import("effect/Brand").Brand<"PermissionV2.ID">;
80
+ };
81
+ readonly effect: Schema.Literals<readonly ["allow", "deny", "ask"]>;
82
+ }>;
83
+ }>>, HttpApiEndpoint.Json<typeof SessionNotFoundError>, SessionLocationId, HttpApiMiddleware.Requires<SessionLocationId>> | HttpApiEndpoint.HttpApiEndpoint<"session.permission.list", "GET", "/api/session/:sessionID/permission", HttpApiEndpoint.StringTree<Schema.Struct<{
84
+ sessionID: Schema.brand<Schema.String, "SessionID"> & {
85
+ create: () => string & import("effect/Brand").Brand<"SessionID">;
86
+ descending: (id?: string) => string & import("effect/Brand").Brand<"SessionID">;
87
+ };
88
+ }>>, HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.Json<Schema.Struct<{
89
+ readonly data: Schema.$Array<Schema.Struct<{
90
+ readonly sessionID: Schema.brand<Schema.String, "SessionID"> & {
91
+ create: () => string & import("effect/Brand").Brand<"SessionID">;
92
+ descending: (id?: string) => string & import("effect/Brand").Brand<"SessionID">;
93
+ };
94
+ readonly action: Schema.String;
95
+ readonly resources: Schema.$Array<Schema.String>;
96
+ readonly save: Schema.decodeTo<Schema.optional<Schema.toType<Schema.$Array<Schema.String>>>, Schema.optionalKey<Schema.$Array<Schema.String>>, never, never>;
97
+ readonly metadata: Schema.decodeTo<Schema.optional<Schema.toType<Schema.$Record<Schema.String, Schema.Unknown>>>, Schema.optionalKey<Schema.$Record<Schema.String, Schema.Unknown>>, never, never>;
98
+ readonly source: Schema.decodeTo<Schema.optional<Schema.toType<Schema.Union<readonly [Schema.Struct<{
99
+ readonly type: Schema.Literal<"tool">;
100
+ readonly messageID: Schema.String;
101
+ readonly callID: Schema.String;
102
+ }>]>>>, Schema.optionalKey<Schema.Union<readonly [Schema.Struct<{
103
+ readonly type: Schema.Literal<"tool">;
104
+ readonly messageID: Schema.String;
105
+ readonly callID: Schema.String;
106
+ }>]>>, never, never>;
107
+ readonly id: Schema.brand<Schema.String, "PermissionV2.ID"> & {
108
+ create: (id?: string) => string & import("effect/Brand").Brand<"PermissionV2.ID">;
109
+ };
110
+ }>>;
111
+ }>>, HttpApiEndpoint.Json<typeof SessionNotFoundError>, SessionLocationId, HttpApiMiddleware.Requires<SessionLocationId>> | HttpApiEndpoint.HttpApiEndpoint<"session.permission.get", "GET", "/api/session/:sessionID/permission/:requestID", HttpApiEndpoint.StringTree<Schema.Struct<{
112
+ sessionID: Schema.brand<Schema.String, "SessionID"> & {
113
+ create: () => string & import("effect/Brand").Brand<"SessionID">;
114
+ descending: (id?: string) => string & import("effect/Brand").Brand<"SessionID">;
115
+ };
116
+ requestID: Schema.brand<Schema.String, "PermissionV2.ID"> & {
117
+ create: (id?: string) => string & import("effect/Brand").Brand<"PermissionV2.ID">;
118
+ };
119
+ }>>, HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.Json<Schema.Struct<{
120
+ readonly data: Schema.Struct<{
121
+ readonly sessionID: Schema.brand<Schema.String, "SessionID"> & {
122
+ create: () => string & import("effect/Brand").Brand<"SessionID">;
123
+ descending: (id?: string) => string & import("effect/Brand").Brand<"SessionID">;
124
+ };
125
+ readonly action: Schema.String;
126
+ readonly resources: Schema.$Array<Schema.String>;
127
+ readonly save: Schema.decodeTo<Schema.optional<Schema.toType<Schema.$Array<Schema.String>>>, Schema.optionalKey<Schema.$Array<Schema.String>>, never, never>;
128
+ readonly metadata: Schema.decodeTo<Schema.optional<Schema.toType<Schema.$Record<Schema.String, Schema.Unknown>>>, Schema.optionalKey<Schema.$Record<Schema.String, Schema.Unknown>>, never, never>;
129
+ readonly source: Schema.decodeTo<Schema.optional<Schema.toType<Schema.Union<readonly [Schema.Struct<{
130
+ readonly type: Schema.Literal<"tool">;
131
+ readonly messageID: Schema.String;
132
+ readonly callID: Schema.String;
133
+ }>]>>>, Schema.optionalKey<Schema.Union<readonly [Schema.Struct<{
134
+ readonly type: Schema.Literal<"tool">;
135
+ readonly messageID: Schema.String;
136
+ readonly callID: Schema.String;
137
+ }>]>>, never, never>;
138
+ readonly id: Schema.brand<Schema.String, "PermissionV2.ID"> & {
139
+ create: (id?: string) => string & import("effect/Brand").Brand<"PermissionV2.ID">;
140
+ };
141
+ }>;
142
+ }>>, HttpApiEndpoint.Json<typeof SessionNotFoundError | typeof PermissionNotFoundError>, SessionLocationId, HttpApiMiddleware.Requires<SessionLocationId>> | HttpApiEndpoint.HttpApiEndpoint<"session.permission.reply", "POST", "/api/session/:sessionID/permission/:requestID/reply", HttpApiEndpoint.StringTree<Schema.Struct<{
143
+ sessionID: Schema.brand<Schema.String, "SessionID"> & {
144
+ create: () => string & import("effect/Brand").Brand<"SessionID">;
145
+ descending: (id?: string) => string & import("effect/Brand").Brand<"SessionID">;
146
+ };
147
+ requestID: Schema.brand<Schema.String, "PermissionV2.ID"> & {
148
+ create: (id?: string) => string & import("effect/Brand").Brand<"PermissionV2.ID">;
149
+ };
150
+ }>>, HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.Json<Schema.Struct<{
151
+ readonly reply: Schema.Literals<readonly ["once", "always", "reject"]>;
152
+ readonly message: Schema.optional<Schema.String>;
153
+ }>>, HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.Json<HttpApiSchema.NoContent>, HttpApiEndpoint.Json<typeof SessionNotFoundError | typeof PermissionNotFoundError>, SessionLocationId, HttpApiMiddleware.Requires<SessionLocationId>>, false>;
@@ -0,0 +1,99 @@
1
+ import { Agent } from "@opencode-ai/schema/agent";
2
+ import { Location } from "@opencode-ai/schema/location";
3
+ import { Permission } from "@opencode-ai/schema/permission";
4
+ import { PermissionSaved } from "@opencode-ai/schema/permission-saved";
5
+ import { Project } from "@opencode-ai/schema/project";
6
+ import { Session } from "@opencode-ai/schema/session";
7
+ import { Context, Schema } from "effect";
8
+ import { HttpApiEndpoint, HttpApiGroup, HttpApiMiddleware, HttpApiSchema, OpenApi } from "effect/unstable/httpapi";
9
+ import { PermissionNotFoundError, SessionNotFoundError } from "../errors.js";
10
+ import { LocationQuery, locationQueryOpenApi } from "./location.js";
11
+ export const makePermissionGroup = (locationMiddleware, sessionLocationMiddleware) => HttpApiGroup.make("server.permission")
12
+ .add(HttpApiEndpoint.get("permission.request.list", "/api/permission/request", {
13
+ query: LocationQuery,
14
+ success: Location.response(Schema.Array(Permission.Request)),
15
+ })
16
+ .annotateMerge(locationQueryOpenApi)
17
+ .annotateMerge(OpenApi.annotations({
18
+ identifier: "v2.permission.request.list",
19
+ summary: "List pending permission requests",
20
+ description: "Retrieve pending permission requests for a location.",
21
+ })))
22
+ .add(HttpApiEndpoint.get("permission.saved.list", "/api/permission/saved", {
23
+ query: Schema.Struct({ projectID: Project.ID.pipe(Schema.optional) }),
24
+ success: Schema.Struct({ data: Schema.Array(PermissionSaved.Info) }),
25
+ }).annotateMerge(OpenApi.annotations({
26
+ identifier: "v2.permission.saved.list",
27
+ summary: "List saved permissions",
28
+ description: "Retrieve saved permissions, optionally filtered by project.",
29
+ })))
30
+ .add(HttpApiEndpoint.delete("permission.saved.remove", "/api/permission/saved/:id", {
31
+ params: { id: PermissionSaved.ID },
32
+ success: HttpApiSchema.NoContent,
33
+ }).annotateMerge(OpenApi.annotations({
34
+ identifier: "v2.permission.saved.remove",
35
+ summary: "Remove saved permission",
36
+ description: "Remove a saved permission by ID.",
37
+ })))
38
+ // Effect applies group middleware only to endpoints already added; session endpoints use session placement below.
39
+ .middleware(locationMiddleware)
40
+ .add(HttpApiEndpoint.post("session.permission.create", "/api/session/:sessionID/permission", {
41
+ params: { sessionID: Session.ID },
42
+ payload: Schema.Struct({
43
+ id: Permission.ID.pipe(Schema.optional),
44
+ action: Permission.Request.fields.action,
45
+ resources: Permission.Request.fields.resources,
46
+ save: Permission.Request.fields.save,
47
+ metadata: Permission.Request.fields.metadata,
48
+ source: Permission.Request.fields.source,
49
+ agent: Agent.ID.pipe(Schema.optional),
50
+ }),
51
+ success: Schema.Struct({
52
+ data: Schema.Struct({ id: Permission.ID, effect: Permission.Effect }),
53
+ }),
54
+ error: SessionNotFoundError,
55
+ })
56
+ .middleware(sessionLocationMiddleware)
57
+ .annotateMerge(OpenApi.annotations({
58
+ identifier: "v2.session.permission.create",
59
+ summary: "Create permission request",
60
+ description: "Evaluate and, when approval is required, create a permission request for a session.",
61
+ })))
62
+ .add(HttpApiEndpoint.get("session.permission.list", "/api/session/:sessionID/permission", {
63
+ params: { sessionID: Session.ID },
64
+ success: Schema.Struct({ data: Schema.Array(Permission.Request) }),
65
+ error: SessionNotFoundError,
66
+ })
67
+ .middleware(sessionLocationMiddleware)
68
+ .annotateMerge(OpenApi.annotations({
69
+ identifier: "v2.session.permission.list",
70
+ summary: "List session permission requests",
71
+ description: "Retrieve pending permission requests owned by a session.",
72
+ })))
73
+ .add(HttpApiEndpoint.get("session.permission.get", "/api/session/:sessionID/permission/:requestID", {
74
+ params: { sessionID: Session.ID, requestID: Permission.ID },
75
+ success: Schema.Struct({ data: Permission.Request }),
76
+ error: [SessionNotFoundError, PermissionNotFoundError],
77
+ })
78
+ .middleware(sessionLocationMiddleware)
79
+ .annotateMerge(OpenApi.annotations({
80
+ identifier: "v2.session.permission.get",
81
+ summary: "Get permission request",
82
+ description: "Retrieve a pending permission request owned by a session.",
83
+ })))
84
+ .add(HttpApiEndpoint.post("session.permission.reply", "/api/session/:sessionID/permission/:requestID/reply", {
85
+ params: { sessionID: Session.ID, requestID: Permission.ID },
86
+ payload: Schema.Struct({
87
+ reply: Permission.Reply,
88
+ message: Schema.String.pipe(Schema.optional),
89
+ }),
90
+ success: HttpApiSchema.NoContent,
91
+ error: [SessionNotFoundError, PermissionNotFoundError],
92
+ })
93
+ .middleware(sessionLocationMiddleware)
94
+ .annotateMerge(OpenApi.annotations({
95
+ identifier: "v2.session.permission.reply",
96
+ summary: "Reply to pending permission request",
97
+ description: "Respond to a pending permission request owned by a session.",
98
+ })))
99
+ .annotateMerge(OpenApi.annotations({ title: "permissions", description: "Experimental permission routes." }));
@@ -0,0 +1,14 @@
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 PluginGroup: HttpApiGroup.HttpApiGroup<"server.plugin", HttpApiEndpoint.HttpApiEndpoint<"plugin.list", "GET", "/api/plugin", 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 id: Schema.brand<Schema.String, "Plugin.ID">;
13
+ }>>;
14
+ }>>, HttpApiEndpoint.Json<never>, never, never>, false>;
@@ -0,0 +1,20 @@
1
+ import { Location } from "@opencode-ai/schema/location";
2
+ import { Plugin } from "@opencode-ai/schema/plugin";
3
+ import { Schema } from "effect";
4
+ import { HttpApiEndpoint, HttpApiGroup, OpenApi } from "effect/unstable/httpapi";
5
+ import { LocationQuery, locationQueryOpenApi } from "./location.js";
6
+ export const PluginGroup = HttpApiGroup.make("server.plugin")
7
+ .add(HttpApiEndpoint.get("plugin.list", "/api/plugin", {
8
+ query: LocationQuery,
9
+ success: Location.response(Schema.Array(Plugin.Info)),
10
+ })
11
+ .annotateMerge(locationQueryOpenApi)
12
+ .annotateMerge(OpenApi.annotations({
13
+ identifier: "v2.plugin.list",
14
+ summary: "List plugins",
15
+ description: "Retrieve currently loaded plugins.",
16
+ })))
17
+ .annotateMerge(OpenApi.annotations({
18
+ title: "plugins",
19
+ description: "Experimental plugin routes.",
20
+ }));
@@ -0,0 +1,49 @@
1
+ import { Schema } from "effect";
2
+ import { HttpApiEndpoint, HttpApiGroup, HttpApiSchema } from "effect/unstable/httpapi";
3
+ declare const ProjectCopyError_base: Schema.Class<ProjectCopyError, Schema.Struct<{
4
+ readonly name: Schema.Literal<"ProjectCopyError">;
5
+ readonly data: Schema.Struct<{
6
+ readonly message: Schema.String;
7
+ readonly forceRequired: Schema.optional<Schema.Boolean>;
8
+ }>;
9
+ }>, import("effect/Cause").YieldableError>;
10
+ export declare class ProjectCopyError extends ProjectCopyError_base {
11
+ }
12
+ export declare const ProjectCopyGroup: HttpApiGroup.HttpApiGroup<"server.projectCopy", HttpApiEndpoint.HttpApiEndpoint<"projectCopy.create", "POST", "/experimental/project/:projectID/copy", HttpApiEndpoint.StringTree<Schema.Struct<{
13
+ projectID: Schema.brand<Schema.String, "Project.ID"> & {
14
+ global: string & import("effect/Brand").Brand<"Project.ID">;
15
+ };
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.Json<Schema.Struct<{
22
+ readonly directory: Schema.brand<Schema.String, "AbsolutePath">;
23
+ readonly name: Schema.decodeTo<Schema.optional<Schema.toType<Schema.String>>, Schema.optionalKey<Schema.String>, never, never>;
24
+ readonly strategy: Schema.brand<Schema.Trim, "ProjectCopy.StrategyID">;
25
+ }>>, HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.Json<Schema.Struct<{
26
+ readonly directory: Schema.brand<Schema.String, "AbsolutePath">;
27
+ }>>, HttpApiEndpoint.Json<typeof ProjectCopyError>, never, never> | HttpApiEndpoint.HttpApiEndpoint<"projectCopy.remove", "DELETE", "/experimental/project/:projectID/copy", HttpApiEndpoint.StringTree<Schema.Struct<{
28
+ projectID: Schema.brand<Schema.String, "Project.ID"> & {
29
+ global: string & import("effect/Brand").Brand<"Project.ID">;
30
+ };
31
+ }>>, HttpApiEndpoint.StringTree<Schema.Struct<{
32
+ readonly location: Schema.optional<Schema.Struct<{
33
+ readonly directory: Schema.optional<Schema.String>;
34
+ readonly workspace: Schema.optional<Schema.String>;
35
+ }>>;
36
+ }>>, HttpApiEndpoint.Json<Schema.Struct<{
37
+ readonly directory: Schema.brand<Schema.String, "AbsolutePath">;
38
+ readonly force: Schema.Boolean;
39
+ }>>, HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.Json<HttpApiSchema.NoContent>, HttpApiEndpoint.Json<typeof ProjectCopyError>, never, never> | HttpApiEndpoint.HttpApiEndpoint<"projectCopy.refresh", "POST", "/experimental/project/:projectID/copy/refresh", HttpApiEndpoint.StringTree<Schema.Struct<{
40
+ projectID: Schema.brand<Schema.String, "Project.ID"> & {
41
+ global: string & import("effect/Brand").Brand<"Project.ID">;
42
+ };
43
+ }>>, HttpApiEndpoint.StringTree<Schema.Struct<{
44
+ readonly location: Schema.optional<Schema.Struct<{
45
+ readonly directory: Schema.optional<Schema.String>;
46
+ readonly workspace: Schema.optional<Schema.String>;
47
+ }>>;
48
+ }>>, HttpApiEndpoint.Json<never>, HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.Json<HttpApiSchema.NoContent>, HttpApiEndpoint.Json<typeof ProjectCopyError>, never, never>, false>;
49
+ export {};
@@ -0,0 +1,44 @@
1
+ import { ProjectCopy } from "@opencode-ai/schema/project-copy";
2
+ import { Project } from "@opencode-ai/schema/project";
3
+ import { Schema, Struct } from "effect";
4
+ import { HttpApiEndpoint, HttpApiGroup, HttpApiSchema, OpenApi } from "effect/unstable/httpapi";
5
+ import { LocationQuery, locationQueryOpenApi } from "./location.js";
6
+ const root = "/experimental/project/:projectID/copy";
7
+ export class ProjectCopyError extends Schema.ErrorClass("ProjectCopyError")({
8
+ name: Schema.Literal("ProjectCopyError"),
9
+ data: Schema.Struct({
10
+ message: Schema.String,
11
+ forceRequired: Schema.optional(Schema.Boolean),
12
+ }),
13
+ }, { httpApiStatus: 400 }) {
14
+ }
15
+ const CreatePayload = Schema.Struct(Struct.omit(ProjectCopy.CreateInput.fields, ["projectID", "sourceDirectory"]));
16
+ const RemovePayload = Schema.Struct(Struct.omit(ProjectCopy.RemoveInput.fields, ["projectID"]));
17
+ export const ProjectCopyGroup = HttpApiGroup.make("server.projectCopy")
18
+ .add(HttpApiEndpoint.post("projectCopy.create", root, {
19
+ params: { projectID: Project.ID },
20
+ query: LocationQuery,
21
+ payload: CreatePayload,
22
+ success: ProjectCopy.Copy,
23
+ error: ProjectCopyError,
24
+ })
25
+ .annotateMerge(locationQueryOpenApi)
26
+ .annotateMerge(OpenApi.annotations({ identifier: "v2.projectCopy.create" })))
27
+ .add(HttpApiEndpoint.delete("projectCopy.remove", root, {
28
+ params: { projectID: Project.ID },
29
+ query: LocationQuery,
30
+ payload: RemovePayload,
31
+ success: HttpApiSchema.NoContent,
32
+ error: ProjectCopyError,
33
+ })
34
+ .annotateMerge(locationQueryOpenApi)
35
+ .annotateMerge(OpenApi.annotations({ identifier: "v2.projectCopy.remove" })))
36
+ .add(HttpApiEndpoint.post("projectCopy.refresh", `${root}/refresh`, {
37
+ params: { projectID: Project.ID },
38
+ query: LocationQuery,
39
+ success: HttpApiSchema.NoContent,
40
+ error: ProjectCopyError,
41
+ })
42
+ .annotateMerge(locationQueryOpenApi)
43
+ .annotateMerge(OpenApi.annotations({ identifier: "v2.projectCopy.refresh" })))
44
+ .annotateMerge(OpenApi.annotations({ title: "projectCopy", description: "Project copy management routes." }));
@@ -0,0 +1,24 @@
1
+ import { HttpApiEndpoint, HttpApiGroup } from "effect/unstable/httpapi";
2
+ export declare const ProjectGroup: HttpApiGroup.HttpApiGroup<"server.project", HttpApiEndpoint.HttpApiEndpoint<"project.current", "GET", "/api/project/current", HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.StringTree<import("effect/Schema").Struct<{
3
+ readonly location: import("effect/Schema").optional<import("effect/Schema").Struct<{
4
+ readonly directory: import("effect/Schema").optional<import("effect/Schema").String>;
5
+ readonly workspace: import("effect/Schema").optional<import("effect/Schema").String>;
6
+ }>>;
7
+ }>>, HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.Json<import("effect/Schema").Struct<{
8
+ readonly id: import("effect/Schema").brand<import("effect/Schema").String, "Project.ID"> & {
9
+ global: string & import("effect/Brand").Brand<"Project.ID">;
10
+ };
11
+ readonly directory: import("effect/Schema").brand<import("effect/Schema").String, "AbsolutePath">;
12
+ }>>, HttpApiEndpoint.Json<never>, never, never> | HttpApiEndpoint.HttpApiEndpoint<"project.directories", "GET", "/api/project/:projectID/directories", HttpApiEndpoint.StringTree<import("effect/Schema").Struct<{
13
+ projectID: import("effect/Schema").brand<import("effect/Schema").String, "Project.ID"> & {
14
+ global: string & import("effect/Brand").Brand<"Project.ID">;
15
+ };
16
+ }>>, HttpApiEndpoint.StringTree<import("effect/Schema").Struct<{
17
+ readonly location: import("effect/Schema").optional<import("effect/Schema").Struct<{
18
+ readonly directory: import("effect/Schema").optional<import("effect/Schema").String>;
19
+ readonly workspace: import("effect/Schema").optional<import("effect/Schema").String>;
20
+ }>>;
21
+ }>>, HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.Json<import("effect/Schema").$Array<import("effect/Schema").Struct<{
22
+ readonly directory: import("effect/Schema").brand<import("effect/Schema").String, "AbsolutePath">;
23
+ readonly strategy: import("effect/Schema").decodeTo<import("effect/Schema").optional<import("effect/Schema").toType<import("effect/Schema").String>>, import("effect/Schema").optionalKey<import("effect/Schema").String>, never, never>;
24
+ }>>>, HttpApiEndpoint.Json<never>, never, never>, false>;
@@ -0,0 +1,30 @@
1
+ import { Project } from "@opencode-ai/schema/project";
2
+ import { HttpApiEndpoint, HttpApiGroup, OpenApi } from "effect/unstable/httpapi";
3
+ import { LocationQuery, locationQueryOpenApi } from "./location.js";
4
+ const root = "/api/project";
5
+ export const ProjectGroup = HttpApiGroup.make("server.project")
6
+ .add(HttpApiEndpoint.get("project.current", `${root}/current`, {
7
+ query: LocationQuery,
8
+ success: Project.Current,
9
+ })
10
+ .annotateMerge(locationQueryOpenApi)
11
+ .annotateMerge(OpenApi.annotations({
12
+ identifier: "v2.project.current",
13
+ summary: "Get current project",
14
+ description: "Resolve the project for the requested location.",
15
+ })))
16
+ .add(HttpApiEndpoint.get("project.directories", `${root}/:projectID/directories`, {
17
+ params: { projectID: Project.ID },
18
+ query: LocationQuery,
19
+ success: Project.Directories,
20
+ })
21
+ .annotateMerge(locationQueryOpenApi)
22
+ .annotateMerge(OpenApi.annotations({
23
+ identifier: "v2.project.directories",
24
+ summary: "List project directories",
25
+ description: "List known local absolute directories for a project.",
26
+ })))
27
+ .annotateMerge(OpenApi.annotations({
28
+ title: "projects",
29
+ description: "Location-scoped project routes.",
30
+ }));
@@ -0,0 +1,156 @@
1
+ import { Provider } from "@opencode-ai/schema/provider";
2
+ import { Location } from "@opencode-ai/schema/location";
3
+ import { Schema } from "effect";
4
+ import { HttpApiEndpoint, HttpApiGroup } from "effect/unstable/httpapi";
5
+ import { ProviderNotFoundError, ServiceUnavailableError } from "../errors.js";
6
+ export declare const ProviderGroup: HttpApiGroup.HttpApiGroup<"server.provider", HttpApiEndpoint.HttpApiEndpoint<"provider.list", "GET", "/api/provider", 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<Schema.Struct<{
14
+ readonly id: Schema.brand<Schema.String, "ProviderV2.ID"> & {
15
+ opencode: string & import("effect/Brand").Brand<"ProviderV2.ID">;
16
+ anthropic: string & import("effect/Brand").Brand<"ProviderV2.ID">;
17
+ openai: string & import("effect/Brand").Brand<"ProviderV2.ID">;
18
+ google: string & import("effect/Brand").Brand<"ProviderV2.ID">;
19
+ googleVertex: string & import("effect/Brand").Brand<"ProviderV2.ID">;
20
+ githubCopilot: string & import("effect/Brand").Brand<"ProviderV2.ID">;
21
+ amazonBedrock: string & import("effect/Brand").Brand<"ProviderV2.ID">;
22
+ azure: string & import("effect/Brand").Brand<"ProviderV2.ID">;
23
+ openrouter: string & import("effect/Brand").Brand<"ProviderV2.ID">;
24
+ mistral: string & import("effect/Brand").Brand<"ProviderV2.ID">;
25
+ gitlab: string & import("effect/Brand").Brand<"ProviderV2.ID">;
26
+ };
27
+ readonly integrationID: Schema.decodeTo<Schema.optional<Schema.toType<Schema.brand<Schema.String, "Integration.ID">>>, Schema.optionalKey<Schema.brand<Schema.String, "Integration.ID">>, never, never>;
28
+ readonly name: Schema.String;
29
+ readonly disabled: Schema.decodeTo<Schema.optional<Schema.toType<Schema.Boolean>>, Schema.optionalKey<Schema.Boolean>, never, never>;
30
+ readonly api: Schema.Union<readonly [Schema.Struct<{
31
+ readonly type: Schema.Literal<"aisdk">;
32
+ readonly package: Schema.String;
33
+ readonly url: Schema.decodeTo<Schema.optional<Schema.toType<Schema.String>>, Schema.optionalKey<Schema.String>, never, never>;
34
+ readonly settings: Schema.decodeTo<Schema.optional<Schema.toType<Schema.$Record<Schema.String, Schema.Unknown>>>, Schema.optionalKey<Schema.$Record<Schema.String, Schema.Unknown>>, never, never>;
35
+ }>, Schema.Struct<{
36
+ readonly type: Schema.Literal<"native">;
37
+ readonly url: Schema.decodeTo<Schema.optional<Schema.toType<Schema.String>>, Schema.optionalKey<Schema.String>, never, never>;
38
+ readonly settings: Schema.$Record<Schema.String, Schema.Unknown>;
39
+ }>]>;
40
+ readonly request: Schema.Struct<{
41
+ readonly headers: Schema.$Record<Schema.String, Schema.String>;
42
+ readonly body: Schema.$Record<Schema.String, Schema.Codec<Schema.Json, Schema.Json, never, never>>;
43
+ }>;
44
+ }> & {
45
+ empty: (id: Provider.ID) => {
46
+ readonly id: string & import("effect/Brand").Brand<"ProviderV2.ID">;
47
+ readonly name: string;
48
+ readonly api: {
49
+ readonly type: "aisdk";
50
+ readonly package: string;
51
+ readonly url?: string | undefined;
52
+ readonly settings?: {
53
+ readonly [x: string]: unknown;
54
+ } | undefined;
55
+ } | {
56
+ readonly type: "native";
57
+ readonly settings: {
58
+ readonly [x: string]: unknown;
59
+ };
60
+ readonly url?: string | undefined;
61
+ };
62
+ readonly request: {
63
+ readonly headers: {
64
+ readonly [x: string]: string;
65
+ };
66
+ readonly body: {
67
+ readonly [x: string]: Schema.Json;
68
+ };
69
+ };
70
+ readonly integrationID?: (string & import("effect/Brand").Brand<"Integration.ID">) | undefined;
71
+ readonly disabled?: boolean | undefined;
72
+ };
73
+ }>;
74
+ }>>, HttpApiEndpoint.Json<typeof ServiceUnavailableError>, never, never> | HttpApiEndpoint.HttpApiEndpoint<"provider.get", "GET", "/api/provider/:providerID", HttpApiEndpoint.StringTree<Schema.Struct<{
75
+ providerID: Schema.brand<Schema.String, "ProviderV2.ID"> & {
76
+ opencode: string & import("effect/Brand").Brand<"ProviderV2.ID">;
77
+ anthropic: string & import("effect/Brand").Brand<"ProviderV2.ID">;
78
+ openai: string & import("effect/Brand").Brand<"ProviderV2.ID">;
79
+ google: string & import("effect/Brand").Brand<"ProviderV2.ID">;
80
+ googleVertex: string & import("effect/Brand").Brand<"ProviderV2.ID">;
81
+ githubCopilot: string & import("effect/Brand").Brand<"ProviderV2.ID">;
82
+ amazonBedrock: string & import("effect/Brand").Brand<"ProviderV2.ID">;
83
+ azure: string & import("effect/Brand").Brand<"ProviderV2.ID">;
84
+ openrouter: string & import("effect/Brand").Brand<"ProviderV2.ID">;
85
+ mistral: string & import("effect/Brand").Brand<"ProviderV2.ID">;
86
+ gitlab: string & import("effect/Brand").Brand<"ProviderV2.ID">;
87
+ };
88
+ }>>, HttpApiEndpoint.StringTree<Schema.Struct<{
89
+ readonly location: Schema.optional<Schema.Struct<{
90
+ readonly directory: Schema.optional<Schema.String>;
91
+ readonly workspace: Schema.optional<Schema.String>;
92
+ }>>;
93
+ }>>, HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.StringTree<never>, HttpApiEndpoint.Json<Schema.Struct<{
94
+ readonly location: typeof Location.Info;
95
+ readonly data: Schema.Struct<{
96
+ readonly id: Schema.brand<Schema.String, "ProviderV2.ID"> & {
97
+ opencode: string & import("effect/Brand").Brand<"ProviderV2.ID">;
98
+ anthropic: string & import("effect/Brand").Brand<"ProviderV2.ID">;
99
+ openai: string & import("effect/Brand").Brand<"ProviderV2.ID">;
100
+ google: string & import("effect/Brand").Brand<"ProviderV2.ID">;
101
+ googleVertex: string & import("effect/Brand").Brand<"ProviderV2.ID">;
102
+ githubCopilot: string & import("effect/Brand").Brand<"ProviderV2.ID">;
103
+ amazonBedrock: string & import("effect/Brand").Brand<"ProviderV2.ID">;
104
+ azure: string & import("effect/Brand").Brand<"ProviderV2.ID">;
105
+ openrouter: string & import("effect/Brand").Brand<"ProviderV2.ID">;
106
+ mistral: string & import("effect/Brand").Brand<"ProviderV2.ID">;
107
+ gitlab: string & import("effect/Brand").Brand<"ProviderV2.ID">;
108
+ };
109
+ readonly integrationID: Schema.decodeTo<Schema.optional<Schema.toType<Schema.brand<Schema.String, "Integration.ID">>>, Schema.optionalKey<Schema.brand<Schema.String, "Integration.ID">>, never, never>;
110
+ readonly name: Schema.String;
111
+ readonly disabled: Schema.decodeTo<Schema.optional<Schema.toType<Schema.Boolean>>, Schema.optionalKey<Schema.Boolean>, never, never>;
112
+ readonly api: Schema.Union<readonly [Schema.Struct<{
113
+ readonly type: Schema.Literal<"aisdk">;
114
+ readonly package: Schema.String;
115
+ readonly url: Schema.decodeTo<Schema.optional<Schema.toType<Schema.String>>, Schema.optionalKey<Schema.String>, never, never>;
116
+ readonly settings: Schema.decodeTo<Schema.optional<Schema.toType<Schema.$Record<Schema.String, Schema.Unknown>>>, Schema.optionalKey<Schema.$Record<Schema.String, Schema.Unknown>>, never, never>;
117
+ }>, Schema.Struct<{
118
+ readonly type: Schema.Literal<"native">;
119
+ readonly url: Schema.decodeTo<Schema.optional<Schema.toType<Schema.String>>, Schema.optionalKey<Schema.String>, never, never>;
120
+ readonly settings: Schema.$Record<Schema.String, Schema.Unknown>;
121
+ }>]>;
122
+ readonly request: Schema.Struct<{
123
+ readonly headers: Schema.$Record<Schema.String, Schema.String>;
124
+ readonly body: Schema.$Record<Schema.String, Schema.Codec<Schema.Json, Schema.Json, never, never>>;
125
+ }>;
126
+ }> & {
127
+ empty: (id: Provider.ID) => {
128
+ readonly id: string & import("effect/Brand").Brand<"ProviderV2.ID">;
129
+ readonly name: string;
130
+ readonly api: {
131
+ readonly type: "aisdk";
132
+ readonly package: string;
133
+ readonly url?: string | undefined;
134
+ readonly settings?: {
135
+ readonly [x: string]: unknown;
136
+ } | undefined;
137
+ } | {
138
+ readonly type: "native";
139
+ readonly settings: {
140
+ readonly [x: string]: unknown;
141
+ };
142
+ readonly url?: string | undefined;
143
+ };
144
+ readonly request: {
145
+ readonly headers: {
146
+ readonly [x: string]: string;
147
+ };
148
+ readonly body: {
149
+ readonly [x: string]: Schema.Json;
150
+ };
151
+ };
152
+ readonly integrationID?: (string & import("effect/Brand").Brand<"Integration.ID">) | undefined;
153
+ readonly disabled?: boolean | undefined;
154
+ };
155
+ };
156
+ }>>, HttpApiEndpoint.Json<typeof ServiceUnavailableError | typeof ProviderNotFoundError>, never, never>, false>;
@@ -0,0 +1,34 @@
1
+ import { Provider } from "@opencode-ai/schema/provider";
2
+ import { Location } from "@opencode-ai/schema/location";
3
+ import { Schema } from "effect";
4
+ import { HttpApiEndpoint, HttpApiGroup, OpenApi } from "effect/unstable/httpapi";
5
+ import { ProviderNotFoundError, ServiceUnavailableError } from "../errors.js";
6
+ import { LocationQuery, locationQueryOpenApi } from "./location.js";
7
+ export const ProviderGroup = HttpApiGroup.make("server.provider")
8
+ .add(HttpApiEndpoint.get("provider.list", "/api/provider", {
9
+ query: LocationQuery,
10
+ success: Location.response(Schema.Array(Provider.Info)),
11
+ error: ServiceUnavailableError,
12
+ })
13
+ .annotateMerge(locationQueryOpenApi)
14
+ .annotateMerge(OpenApi.annotations({
15
+ identifier: "v2.provider.list",
16
+ summary: "List providers",
17
+ description: "Retrieve active AI providers so clients can show provider availability and configuration.",
18
+ })))
19
+ .add(HttpApiEndpoint.get("provider.get", "/api/provider/:providerID", {
20
+ params: { providerID: Provider.ID },
21
+ query: LocationQuery,
22
+ success: Location.response(Provider.Info),
23
+ error: [ProviderNotFoundError, ServiceUnavailableError],
24
+ })
25
+ .annotateMerge(locationQueryOpenApi)
26
+ .annotateMerge(OpenApi.annotations({
27
+ identifier: "v2.provider.get",
28
+ summary: "Get provider",
29
+ description: "Retrieve a single AI provider so clients can inspect its availability and endpoint settings.",
30
+ })))
31
+ .annotateMerge(OpenApi.annotations({
32
+ title: "providers",
33
+ description: "Experimental provider routes.",
34
+ }));