@opencode-ai/protocol 0.0.0-dev-17471
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.
- package/dist/api.d.ts +53 -0
- package/dist/api.js +73 -0
- package/dist/client.d.ts +61 -0
- package/dist/client.js +47 -0
- package/dist/errors.d.ts +133 -0
- package/dist/errors.js +105 -0
- package/dist/groups/agent.d.ts +194 -0
- package/dist/groups/agent.js +30 -0
- package/dist/groups/command.d.ts +63 -0
- package/dist/groups/command.js +20 -0
- package/dist/groups/config.d.ts +9 -0
- package/dist/groups/config.js +16 -0
- package/dist/groups/credential.d.ts +23 -0
- package/dist/groups/credential.js +29 -0
- package/dist/groups/debug.d.ts +17 -0
- package/dist/groups/debug.js +23 -0
- package/dist/groups/event.d.ts +12882 -0
- package/dist/groups/event.js +42 -0
- package/dist/groups/form.d.ts +781 -0
- package/dist/groups/form.js +97 -0
- package/dist/groups/fs.d.ts +35 -0
- package/dist/groups/fs.js +51 -0
- package/dist/groups/generate.d.ts +38 -0
- package/dist/groups/generate.js +27 -0
- package/dist/groups/health.d.ts +27 -0
- package/dist/groups/health.js +34 -0
- package/dist/groups/integration.d.ts +1152 -0
- package/dist/groups/integration.js +149 -0
- package/dist/groups/location.d.ts +16 -0
- package/dist/groups/location.js +34 -0
- package/dist/groups/mcp.d.ts +82 -0
- package/dist/groups/mcp.js +78 -0
- package/dist/groups/message.d.ts +592 -0
- package/dist/groups/message.js +37 -0
- package/dist/groups/migration.d.ts +28 -0
- package/dist/groups/migration.js +21 -0
- package/dist/groups/model.d.ts +218 -0
- package/dist/groups/model.js +33 -0
- package/dist/groups/permission.d.ts +153 -0
- package/dist/groups/permission.js +99 -0
- package/dist/groups/plugin.d.ts +14 -0
- package/dist/groups/plugin.js +20 -0
- package/dist/groups/project.d.ts +41 -0
- package/dist/groups/project.js +27 -0
- package/dist/groups/provider.d.ts +82 -0
- package/dist/groups/provider.js +34 -0
- package/dist/groups/pty.d.ts +145 -0
- package/dist/groups/pty.js +112 -0
- package/dist/groups/reference.d.ts +29 -0
- package/dist/groups/reference.js +20 -0
- package/dist/groups/server.d.ts +5 -0
- package/dist/groups/server.js +11 -0
- package/dist/groups/session.d.ts +9247 -0
- package/dist/groups/session.js +515 -0
- package/dist/groups/shell.d.ts +152 -0
- package/dist/groups/shell.js +82 -0
- package/dist/groups/skill.d.ts +20 -0
- package/dist/groups/skill.js +20 -0
- package/dist/groups/vcs.d.ts +46 -0
- package/dist/groups/vcs.js +47 -0
- package/dist/groups/websearch.d.ts +28 -0
- package/dist/groups/websearch.js +34 -0
- package/dist/groups/worktree.d.ts +42 -0
- package/dist/groups/worktree.js +54 -0
- package/dist/middleware/authorization.d.ts +13 -0
- package/dist/middleware/authorization.js +6 -0
- package/dist/middleware/schema-error.d.ts +13 -0
- package/dist/middleware/schema-error.js +4 -0
- package/dist/simulation.d.ts +1590 -0
- package/dist/simulation.js +460 -0
- package/package.json +44 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { Schema } from "effect";
|
|
2
|
+
import { HttpApiEndpoint, HttpApiGroup } from "effect/unstable/httpapi";
|
|
3
|
+
export declare const ProjectGroup: HttpApiGroup.HttpApiGroup<"server.project", HttpApiEndpoint.HttpApiEndpoint<"project.list", "GET", "/api/project", never, never, never, never, Schema.toCodecJson<Schema.$Array<Schema.Struct<{
|
|
4
|
+
readonly id: Schema.brand<Schema.String, "Project.ID"> & {
|
|
5
|
+
global: string & import("effect/Brand").Brand<"Project.ID">;
|
|
6
|
+
};
|
|
7
|
+
readonly canonical: Schema.brand<Schema.String, "AbsolutePath">;
|
|
8
|
+
readonly vcs: Schema.decodeTo<Schema.optional<Schema.toType<Schema.Literals<readonly ["git", "hg"]>>>, Schema.optionalKey<Schema.Literals<readonly ["git", "hg"]>>, never, never>;
|
|
9
|
+
readonly name: Schema.decodeTo<Schema.optional<Schema.toType<Schema.String>>, Schema.optionalKey<Schema.String>, never, never>;
|
|
10
|
+
readonly icon: Schema.decodeTo<Schema.optional<Schema.toType<Schema.Struct<{
|
|
11
|
+
readonly url: Schema.decodeTo<Schema.optional<Schema.toType<Schema.String>>, Schema.optionalKey<Schema.String>, never, never>;
|
|
12
|
+
readonly override: Schema.decodeTo<Schema.optional<Schema.toType<Schema.String>>, Schema.optionalKey<Schema.String>, never, never>;
|
|
13
|
+
readonly color: Schema.decodeTo<Schema.optional<Schema.toType<Schema.String>>, Schema.optionalKey<Schema.String>, never, never>;
|
|
14
|
+
}>>>, Schema.optionalKey<Schema.Struct<{
|
|
15
|
+
readonly url: Schema.decodeTo<Schema.optional<Schema.toType<Schema.String>>, Schema.optionalKey<Schema.String>, never, never>;
|
|
16
|
+
readonly override: Schema.decodeTo<Schema.optional<Schema.toType<Schema.String>>, Schema.optionalKey<Schema.String>, never, never>;
|
|
17
|
+
readonly color: Schema.decodeTo<Schema.optional<Schema.toType<Schema.String>>, Schema.optionalKey<Schema.String>, never, never>;
|
|
18
|
+
}>>, never, never>;
|
|
19
|
+
readonly commands: Schema.decodeTo<Schema.optional<Schema.toType<Schema.Struct<{
|
|
20
|
+
readonly start: Schema.decodeTo<Schema.optional<Schema.toType<Schema.String>>, Schema.optionalKey<Schema.String>, never, never>;
|
|
21
|
+
}>>>, Schema.optionalKey<Schema.Struct<{
|
|
22
|
+
readonly start: Schema.decodeTo<Schema.optional<Schema.toType<Schema.String>>, Schema.optionalKey<Schema.String>, never, never>;
|
|
23
|
+
}>>, never, never>;
|
|
24
|
+
readonly time: Schema.Struct<{
|
|
25
|
+
readonly created: Schema.Int;
|
|
26
|
+
readonly updated: Schema.Int;
|
|
27
|
+
readonly initialized: Schema.decodeTo<Schema.optional<Schema.toType<Schema.Int>>, Schema.optionalKey<Schema.Int>, never, never>;
|
|
28
|
+
}>;
|
|
29
|
+
readonly sandboxes: Schema.$Array<Schema.String>;
|
|
30
|
+
}>>>, never, never, never> | HttpApiEndpoint.HttpApiEndpoint<"project.current", "GET", "/api/project/current", never, Schema.toCodecStringTree<Schema.Struct<{
|
|
31
|
+
readonly location: Schema.optional<Schema.Struct<{
|
|
32
|
+
readonly directory: Schema.optional<Schema.String>;
|
|
33
|
+
readonly workspace: Schema.optional<Schema.String>;
|
|
34
|
+
}>>;
|
|
35
|
+
}>>, never, never, Schema.toCodecJson<Schema.Struct<{
|
|
36
|
+
readonly id: Schema.brand<Schema.String, "Project.ID"> & {
|
|
37
|
+
global: string & import("effect/Brand").Brand<"Project.ID">;
|
|
38
|
+
};
|
|
39
|
+
readonly directory: Schema.brand<Schema.String, "AbsolutePath">;
|
|
40
|
+
readonly canonical: Schema.brand<Schema.String, "AbsolutePath">;
|
|
41
|
+
}>>, never, never, never>, false>;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Project } from "@opencode-ai/schema/project";
|
|
2
|
+
import { Schema } from "effect";
|
|
3
|
+
import { HttpApiEndpoint, HttpApiGroup, OpenApi } from "effect/unstable/httpapi";
|
|
4
|
+
import { LocationQuery, locationQueryOpenApi } from "./location.js";
|
|
5
|
+
const root = "/api/project";
|
|
6
|
+
export const ProjectGroup = HttpApiGroup.make("server.project")
|
|
7
|
+
.add(HttpApiEndpoint.get("project.list", root, {
|
|
8
|
+
success: Schema.Array(Project.Info),
|
|
9
|
+
}).annotateMerge(OpenApi.annotations({
|
|
10
|
+
identifier: "v2.project.list",
|
|
11
|
+
summary: "List projects",
|
|
12
|
+
description: "List known projects.",
|
|
13
|
+
})))
|
|
14
|
+
.add(HttpApiEndpoint.get("project.current", `${root}/current`, {
|
|
15
|
+
query: LocationQuery,
|
|
16
|
+
success: Project.Current,
|
|
17
|
+
})
|
|
18
|
+
.annotateMerge(locationQueryOpenApi)
|
|
19
|
+
.annotateMerge(OpenApi.annotations({
|
|
20
|
+
identifier: "v2.project.current",
|
|
21
|
+
summary: "Get current project",
|
|
22
|
+
description: "Resolve the project for the requested location.",
|
|
23
|
+
})))
|
|
24
|
+
.annotateMerge(OpenApi.annotations({
|
|
25
|
+
title: "project",
|
|
26
|
+
description: "Project routes.",
|
|
27
|
+
}));
|
|
@@ -0,0 +1,82 @@
|
|
|
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", never, Schema.toCodecStringTree<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
|
+
}>>, never, never, Schema.toCodecJson<Schema.Struct<{
|
|
12
|
+
readonly location: typeof Location.Info;
|
|
13
|
+
readonly data: Schema.$Array<Schema.Struct<{
|
|
14
|
+
readonly settings: Schema.decodeTo<Schema.optional<Schema.toType<Schema.$Record<Schema.String, Schema.Any>>>, Schema.optionalKey<Schema.$Record<Schema.String, Schema.Any>>, never, never>;
|
|
15
|
+
readonly headers: Schema.decodeTo<Schema.optional<Schema.toType<Schema.$Record<Schema.String, Schema.String>>>, Schema.optionalKey<Schema.$Record<Schema.String, Schema.String>>, never, never>;
|
|
16
|
+
readonly body: Schema.decodeTo<Schema.optional<Schema.toType<Schema.$Record<Schema.String, Schema.Any>>>, Schema.optionalKey<Schema.$Record<Schema.String, Schema.Any>>, never, never>;
|
|
17
|
+
readonly id: Schema.brand<Schema.String, "Provider.ID"> & {
|
|
18
|
+
opencode: string & import("effect/Brand").Brand<"Provider.ID">;
|
|
19
|
+
anthropic: string & import("effect/Brand").Brand<"Provider.ID">;
|
|
20
|
+
openai: string & import("effect/Brand").Brand<"Provider.ID">;
|
|
21
|
+
google: string & import("effect/Brand").Brand<"Provider.ID">;
|
|
22
|
+
googleVertex: string & import("effect/Brand").Brand<"Provider.ID">;
|
|
23
|
+
githubCopilot: string & import("effect/Brand").Brand<"Provider.ID">;
|
|
24
|
+
amazonBedrock: string & import("effect/Brand").Brand<"Provider.ID">;
|
|
25
|
+
azure: string & import("effect/Brand").Brand<"Provider.ID">;
|
|
26
|
+
openrouter: string & import("effect/Brand").Brand<"Provider.ID">;
|
|
27
|
+
mistral: string & import("effect/Brand").Brand<"Provider.ID">;
|
|
28
|
+
gitlab: string & import("effect/Brand").Brand<"Provider.ID">;
|
|
29
|
+
};
|
|
30
|
+
readonly integrationID: Schema.decodeTo<Schema.optional<Schema.toType<Schema.brand<Schema.String, "Integration.ID">>>, Schema.optionalKey<Schema.brand<Schema.String, "Integration.ID">>, never, never>;
|
|
31
|
+
readonly name: Schema.String;
|
|
32
|
+
readonly activation: Schema.Literals<readonly ["auto", "enabled", "disabled"]>;
|
|
33
|
+
readonly package: Schema.String;
|
|
34
|
+
}> & {
|
|
35
|
+
empty: (id: Provider.ID) => Provider.Info;
|
|
36
|
+
}>;
|
|
37
|
+
}>>, Schema.toCodecJson<typeof ServiceUnavailableError>, never, never> | HttpApiEndpoint.HttpApiEndpoint<"provider.get", "GET", "/api/provider/:providerID", Schema.toCodecStringTree<Schema.Struct<{
|
|
38
|
+
providerID: Schema.brand<Schema.String, "Provider.ID"> & {
|
|
39
|
+
opencode: string & import("effect/Brand").Brand<"Provider.ID">;
|
|
40
|
+
anthropic: string & import("effect/Brand").Brand<"Provider.ID">;
|
|
41
|
+
openai: string & import("effect/Brand").Brand<"Provider.ID">;
|
|
42
|
+
google: string & import("effect/Brand").Brand<"Provider.ID">;
|
|
43
|
+
googleVertex: string & import("effect/Brand").Brand<"Provider.ID">;
|
|
44
|
+
githubCopilot: string & import("effect/Brand").Brand<"Provider.ID">;
|
|
45
|
+
amazonBedrock: string & import("effect/Brand").Brand<"Provider.ID">;
|
|
46
|
+
azure: string & import("effect/Brand").Brand<"Provider.ID">;
|
|
47
|
+
openrouter: string & import("effect/Brand").Brand<"Provider.ID">;
|
|
48
|
+
mistral: string & import("effect/Brand").Brand<"Provider.ID">;
|
|
49
|
+
gitlab: string & import("effect/Brand").Brand<"Provider.ID">;
|
|
50
|
+
};
|
|
51
|
+
}>>, Schema.toCodecStringTree<Schema.Struct<{
|
|
52
|
+
readonly location: Schema.optional<Schema.Struct<{
|
|
53
|
+
readonly directory: Schema.optional<Schema.String>;
|
|
54
|
+
readonly workspace: Schema.optional<Schema.String>;
|
|
55
|
+
}>>;
|
|
56
|
+
}>>, never, never, Schema.toCodecJson<Schema.Struct<{
|
|
57
|
+
readonly location: typeof Location.Info;
|
|
58
|
+
readonly data: Schema.Struct<{
|
|
59
|
+
readonly settings: Schema.decodeTo<Schema.optional<Schema.toType<Schema.$Record<Schema.String, Schema.Any>>>, Schema.optionalKey<Schema.$Record<Schema.String, Schema.Any>>, never, never>;
|
|
60
|
+
readonly headers: Schema.decodeTo<Schema.optional<Schema.toType<Schema.$Record<Schema.String, Schema.String>>>, Schema.optionalKey<Schema.$Record<Schema.String, Schema.String>>, never, never>;
|
|
61
|
+
readonly body: Schema.decodeTo<Schema.optional<Schema.toType<Schema.$Record<Schema.String, Schema.Any>>>, Schema.optionalKey<Schema.$Record<Schema.String, Schema.Any>>, never, never>;
|
|
62
|
+
readonly id: Schema.brand<Schema.String, "Provider.ID"> & {
|
|
63
|
+
opencode: string & import("effect/Brand").Brand<"Provider.ID">;
|
|
64
|
+
anthropic: string & import("effect/Brand").Brand<"Provider.ID">;
|
|
65
|
+
openai: string & import("effect/Brand").Brand<"Provider.ID">;
|
|
66
|
+
google: string & import("effect/Brand").Brand<"Provider.ID">;
|
|
67
|
+
googleVertex: string & import("effect/Brand").Brand<"Provider.ID">;
|
|
68
|
+
githubCopilot: string & import("effect/Brand").Brand<"Provider.ID">;
|
|
69
|
+
amazonBedrock: string & import("effect/Brand").Brand<"Provider.ID">;
|
|
70
|
+
azure: string & import("effect/Brand").Brand<"Provider.ID">;
|
|
71
|
+
openrouter: string & import("effect/Brand").Brand<"Provider.ID">;
|
|
72
|
+
mistral: string & import("effect/Brand").Brand<"Provider.ID">;
|
|
73
|
+
gitlab: string & import("effect/Brand").Brand<"Provider.ID">;
|
|
74
|
+
};
|
|
75
|
+
readonly integrationID: Schema.decodeTo<Schema.optional<Schema.toType<Schema.brand<Schema.String, "Integration.ID">>>, Schema.optionalKey<Schema.brand<Schema.String, "Integration.ID">>, never, never>;
|
|
76
|
+
readonly name: Schema.String;
|
|
77
|
+
readonly activation: Schema.Literals<readonly ["auto", "enabled", "disabled"]>;
|
|
78
|
+
readonly package: Schema.String;
|
|
79
|
+
}> & {
|
|
80
|
+
empty: (id: Provider.ID) => Provider.Info;
|
|
81
|
+
};
|
|
82
|
+
}>>, Schema.toCodecJson<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: "provider",
|
|
33
|
+
description: "Experimental provider routes.",
|
|
34
|
+
}));
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { Location } from "@opencode-ai/schema/location";
|
|
2
|
+
import { Schema } from "effect";
|
|
3
|
+
import { HttpApiEndpoint, HttpApiGroup, HttpApiSchema } from "effect/unstable/httpapi";
|
|
4
|
+
import { ForbiddenError, PtyNotFoundError } from "../errors.js";
|
|
5
|
+
export declare const PTY_CONNECT_TICKET_QUERY = "ticket";
|
|
6
|
+
export declare const PTY_CONNECT_TOKEN_HEADER = "x-opencode-ticket";
|
|
7
|
+
export declare const PTY_CONNECT_TOKEN_HEADER_VALUE = "1";
|
|
8
|
+
export declare function hasPtyConnectTicketURL(url: URL): boolean;
|
|
9
|
+
export declare const PtyGroup: HttpApiGroup.HttpApiGroup<"server.pty", HttpApiEndpoint.HttpApiEndpoint<"pty.list", "GET", "/api/pty", never, Schema.toCodecStringTree<Schema.Struct<{
|
|
10
|
+
readonly location: Schema.optional<Schema.Struct<{
|
|
11
|
+
readonly directory: Schema.optional<Schema.String>;
|
|
12
|
+
readonly workspace: Schema.optional<Schema.String>;
|
|
13
|
+
}>>;
|
|
14
|
+
}>>, never, never, Schema.toCodecJson<Schema.Struct<{
|
|
15
|
+
readonly location: typeof Location.Info;
|
|
16
|
+
readonly data: Schema.$Array<Schema.Struct<{
|
|
17
|
+
readonly id: Schema.brand<Schema.String, "PtyID"> & {
|
|
18
|
+
create: () => string & import("effect/Brand").Brand<"PtyID">;
|
|
19
|
+
ascending: (id?: string) => string & import("effect/Brand").Brand<"PtyID">;
|
|
20
|
+
};
|
|
21
|
+
readonly title: Schema.String;
|
|
22
|
+
readonly command: Schema.String;
|
|
23
|
+
readonly args: Schema.$Array<Schema.String>;
|
|
24
|
+
readonly cwd: Schema.String;
|
|
25
|
+
readonly status: Schema.Literals<readonly ["running", "exited"]>;
|
|
26
|
+
readonly pid: Schema.Int;
|
|
27
|
+
readonly exitCode: Schema.decodeTo<Schema.optional<Schema.toType<Schema.Int>>, Schema.optionalKey<Schema.Int>, never, never>;
|
|
28
|
+
}>>;
|
|
29
|
+
}>>, never, never, never> | HttpApiEndpoint.HttpApiEndpoint<"pty.create", "POST", "/api/pty", never, Schema.toCodecStringTree<Schema.Struct<{
|
|
30
|
+
readonly location: Schema.optional<Schema.Struct<{
|
|
31
|
+
readonly directory: Schema.optional<Schema.String>;
|
|
32
|
+
readonly workspace: Schema.optional<Schema.String>;
|
|
33
|
+
}>>;
|
|
34
|
+
}>>, Schema.toCodecJson<Schema.Struct<{
|
|
35
|
+
readonly command: Schema.decodeTo<Schema.optional<Schema.toType<Schema.String>>, Schema.optionalKey<Schema.String>, never, never>;
|
|
36
|
+
readonly args: Schema.decodeTo<Schema.optional<Schema.toType<Schema.$Array<Schema.String>>>, Schema.optionalKey<Schema.$Array<Schema.String>>, never, never>;
|
|
37
|
+
readonly cwd: Schema.decodeTo<Schema.optional<Schema.toType<Schema.String>>, Schema.optionalKey<Schema.String>, never, never>;
|
|
38
|
+
readonly title: Schema.decodeTo<Schema.optional<Schema.toType<Schema.String>>, Schema.optionalKey<Schema.String>, never, never>;
|
|
39
|
+
readonly env: Schema.decodeTo<Schema.optional<Schema.toType<Schema.$Record<Schema.String, Schema.String>>>, Schema.optionalKey<Schema.$Record<Schema.String, Schema.String>>, never, never>;
|
|
40
|
+
}>>, never, Schema.toCodecJson<Schema.Struct<{
|
|
41
|
+
readonly location: typeof Location.Info;
|
|
42
|
+
readonly data: Schema.Struct<{
|
|
43
|
+
readonly id: Schema.brand<Schema.String, "PtyID"> & {
|
|
44
|
+
create: () => string & import("effect/Brand").Brand<"PtyID">;
|
|
45
|
+
ascending: (id?: string) => string & import("effect/Brand").Brand<"PtyID">;
|
|
46
|
+
};
|
|
47
|
+
readonly title: Schema.String;
|
|
48
|
+
readonly command: Schema.String;
|
|
49
|
+
readonly args: Schema.$Array<Schema.String>;
|
|
50
|
+
readonly cwd: Schema.String;
|
|
51
|
+
readonly status: Schema.Literals<readonly ["running", "exited"]>;
|
|
52
|
+
readonly pid: Schema.Int;
|
|
53
|
+
readonly exitCode: Schema.decodeTo<Schema.optional<Schema.toType<Schema.Int>>, Schema.optionalKey<Schema.Int>, never, never>;
|
|
54
|
+
}>;
|
|
55
|
+
}>>, never, never, never> | HttpApiEndpoint.HttpApiEndpoint<"pty.get", "GET", "/api/pty/:ptyID", Schema.toCodecStringTree<Schema.Struct<{
|
|
56
|
+
ptyID: Schema.brand<Schema.String, "PtyID"> & {
|
|
57
|
+
create: () => string & import("effect/Brand").Brand<"PtyID">;
|
|
58
|
+
ascending: (id?: string) => string & import("effect/Brand").Brand<"PtyID">;
|
|
59
|
+
};
|
|
60
|
+
}>>, Schema.toCodecStringTree<Schema.Struct<{
|
|
61
|
+
readonly location: Schema.optional<Schema.Struct<{
|
|
62
|
+
readonly directory: Schema.optional<Schema.String>;
|
|
63
|
+
readonly workspace: Schema.optional<Schema.String>;
|
|
64
|
+
}>>;
|
|
65
|
+
}>>, never, never, Schema.toCodecJson<Schema.Struct<{
|
|
66
|
+
readonly location: typeof Location.Info;
|
|
67
|
+
readonly data: Schema.Struct<{
|
|
68
|
+
readonly id: Schema.brand<Schema.String, "PtyID"> & {
|
|
69
|
+
create: () => string & import("effect/Brand").Brand<"PtyID">;
|
|
70
|
+
ascending: (id?: string) => string & import("effect/Brand").Brand<"PtyID">;
|
|
71
|
+
};
|
|
72
|
+
readonly title: Schema.String;
|
|
73
|
+
readonly command: Schema.String;
|
|
74
|
+
readonly args: Schema.$Array<Schema.String>;
|
|
75
|
+
readonly cwd: Schema.String;
|
|
76
|
+
readonly status: Schema.Literals<readonly ["running", "exited"]>;
|
|
77
|
+
readonly pid: Schema.Int;
|
|
78
|
+
readonly exitCode: Schema.decodeTo<Schema.optional<Schema.toType<Schema.Int>>, Schema.optionalKey<Schema.Int>, never, never>;
|
|
79
|
+
}>;
|
|
80
|
+
}>>, Schema.toCodecJson<typeof PtyNotFoundError>, never, never> | HttpApiEndpoint.HttpApiEndpoint<"pty.update", "PUT", "/api/pty/:ptyID", Schema.toCodecStringTree<Schema.Struct<{
|
|
81
|
+
ptyID: Schema.brand<Schema.String, "PtyID"> & {
|
|
82
|
+
create: () => string & import("effect/Brand").Brand<"PtyID">;
|
|
83
|
+
ascending: (id?: string) => string & import("effect/Brand").Brand<"PtyID">;
|
|
84
|
+
};
|
|
85
|
+
}>>, Schema.toCodecStringTree<Schema.Struct<{
|
|
86
|
+
readonly location: Schema.optional<Schema.Struct<{
|
|
87
|
+
readonly directory: Schema.optional<Schema.String>;
|
|
88
|
+
readonly workspace: Schema.optional<Schema.String>;
|
|
89
|
+
}>>;
|
|
90
|
+
}>>, Schema.toCodecJson<Schema.Struct<{
|
|
91
|
+
readonly title: Schema.decodeTo<Schema.optional<Schema.toType<Schema.String>>, Schema.optionalKey<Schema.String>, never, never>;
|
|
92
|
+
readonly size: Schema.decodeTo<Schema.optional<Schema.toType<Schema.Struct<{
|
|
93
|
+
readonly rows: Schema.Int;
|
|
94
|
+
readonly cols: Schema.Int;
|
|
95
|
+
}>>>, Schema.optionalKey<Schema.Struct<{
|
|
96
|
+
readonly rows: Schema.Int;
|
|
97
|
+
readonly cols: Schema.Int;
|
|
98
|
+
}>>, never, never>;
|
|
99
|
+
}>>, never, Schema.toCodecJson<Schema.Struct<{
|
|
100
|
+
readonly location: typeof Location.Info;
|
|
101
|
+
readonly data: Schema.Struct<{
|
|
102
|
+
readonly id: Schema.brand<Schema.String, "PtyID"> & {
|
|
103
|
+
create: () => string & import("effect/Brand").Brand<"PtyID">;
|
|
104
|
+
ascending: (id?: string) => string & import("effect/Brand").Brand<"PtyID">;
|
|
105
|
+
};
|
|
106
|
+
readonly title: Schema.String;
|
|
107
|
+
readonly command: Schema.String;
|
|
108
|
+
readonly args: Schema.$Array<Schema.String>;
|
|
109
|
+
readonly cwd: Schema.String;
|
|
110
|
+
readonly status: Schema.Literals<readonly ["running", "exited"]>;
|
|
111
|
+
readonly pid: Schema.Int;
|
|
112
|
+
readonly exitCode: Schema.decodeTo<Schema.optional<Schema.toType<Schema.Int>>, Schema.optionalKey<Schema.Int>, never, never>;
|
|
113
|
+
}>;
|
|
114
|
+
}>>, Schema.toCodecJson<typeof PtyNotFoundError>, never, never> | HttpApiEndpoint.HttpApiEndpoint<"pty.remove", "DELETE", "/api/pty/:ptyID", Schema.toCodecStringTree<Schema.Struct<{
|
|
115
|
+
ptyID: Schema.brand<Schema.String, "PtyID"> & {
|
|
116
|
+
create: () => string & import("effect/Brand").Brand<"PtyID">;
|
|
117
|
+
ascending: (id?: string) => string & import("effect/Brand").Brand<"PtyID">;
|
|
118
|
+
};
|
|
119
|
+
}>>, Schema.toCodecStringTree<Schema.Struct<{
|
|
120
|
+
readonly location: Schema.optional<Schema.Struct<{
|
|
121
|
+
readonly directory: Schema.optional<Schema.String>;
|
|
122
|
+
readonly workspace: Schema.optional<Schema.String>;
|
|
123
|
+
}>>;
|
|
124
|
+
}>>, never, never, Schema.toCodecJson<HttpApiSchema.NoContent>, Schema.toCodecJson<typeof PtyNotFoundError>, never, never> | HttpApiEndpoint.HttpApiEndpoint<"pty.connectToken", "POST", "/api/pty/:ptyID/connect-token", Schema.toCodecStringTree<Schema.Struct<{
|
|
125
|
+
ptyID: Schema.brand<Schema.String, "PtyID"> & {
|
|
126
|
+
create: () => string & import("effect/Brand").Brand<"PtyID">;
|
|
127
|
+
ascending: (id?: string) => string & import("effect/Brand").Brand<"PtyID">;
|
|
128
|
+
};
|
|
129
|
+
}>>, Schema.toCodecStringTree<Schema.Struct<{
|
|
130
|
+
readonly location: Schema.optional<Schema.Struct<{
|
|
131
|
+
readonly directory: Schema.optional<Schema.String>;
|
|
132
|
+
readonly workspace: Schema.optional<Schema.String>;
|
|
133
|
+
}>>;
|
|
134
|
+
}>>, never, never, Schema.toCodecJson<Schema.Struct<{
|
|
135
|
+
readonly location: typeof Location.Info;
|
|
136
|
+
readonly data: Schema.Struct<{
|
|
137
|
+
readonly ticket: Schema.String;
|
|
138
|
+
readonly expires_in: Schema.Int;
|
|
139
|
+
}>;
|
|
140
|
+
}>>, Schema.toCodecJson<typeof ForbiddenError | typeof PtyNotFoundError>, never, never> | HttpApiEndpoint.HttpApiEndpoint<"pty.connect", "GET", "/api/pty/:ptyID/connect", Schema.toCodecStringTree<Schema.Struct<{
|
|
141
|
+
ptyID: Schema.brand<Schema.String, "PtyID"> & {
|
|
142
|
+
create: () => string & import("effect/Brand").Brand<"PtyID">;
|
|
143
|
+
ascending: (id?: string) => string & import("effect/Brand").Brand<"PtyID">;
|
|
144
|
+
};
|
|
145
|
+
}>>, never, never, never, Schema.toCodecJson<Schema.Boolean>, Schema.toCodecJson<typeof ForbiddenError | typeof PtyNotFoundError>, never, never>, false>;
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { Pty } from "@opencode-ai/schema/pty";
|
|
2
|
+
import { PtyTicket } from "@opencode-ai/schema/pty-ticket";
|
|
3
|
+
import { Location } from "@opencode-ai/schema/location";
|
|
4
|
+
import { Schema } from "effect";
|
|
5
|
+
import { HttpApiEndpoint, HttpApiGroup, HttpApiSchema, OpenApi } from "effect/unstable/httpapi";
|
|
6
|
+
import { ForbiddenError, PtyNotFoundError } from "../errors.js";
|
|
7
|
+
import { LocationQuery, locationQueryOpenApi } from "./location.js";
|
|
8
|
+
export const PTY_CONNECT_TICKET_QUERY = "ticket";
|
|
9
|
+
export const PTY_CONNECT_TOKEN_HEADER = "x-opencode-ticket";
|
|
10
|
+
export const PTY_CONNECT_TOKEN_HEADER_VALUE = "1";
|
|
11
|
+
const PTY_CONNECT_PATH = /^\/api\/pty\/[^/]+\/connect$/;
|
|
12
|
+
// Authorization middleware skips credential checks when this matches; the PTY connect handler
|
|
13
|
+
// is then responsible for consuming and validating the ticket.
|
|
14
|
+
export function hasPtyConnectTicketURL(url) {
|
|
15
|
+
return PTY_CONNECT_PATH.test(url.pathname) && !!url.searchParams.get(PTY_CONNECT_TICKET_QUERY);
|
|
16
|
+
}
|
|
17
|
+
export const PtyGroup = HttpApiGroup.make("server.pty")
|
|
18
|
+
.add(HttpApiEndpoint.get("pty.list", "/api/pty", {
|
|
19
|
+
query: LocationQuery,
|
|
20
|
+
success: Location.response(Schema.Array(Pty.Info)),
|
|
21
|
+
})
|
|
22
|
+
.annotateMerge(locationQueryOpenApi)
|
|
23
|
+
.annotateMerge(OpenApi.annotations({
|
|
24
|
+
identifier: "v2.pty.list",
|
|
25
|
+
summary: "List PTY sessions",
|
|
26
|
+
description: "List PTY sessions for a location, including exited sessions retained until removal.",
|
|
27
|
+
})))
|
|
28
|
+
.add(HttpApiEndpoint.post("pty.create", "/api/pty", {
|
|
29
|
+
query: LocationQuery,
|
|
30
|
+
payload: Pty.CreateInput,
|
|
31
|
+
success: Location.response(Pty.Info),
|
|
32
|
+
})
|
|
33
|
+
.annotateMerge(locationQueryOpenApi)
|
|
34
|
+
.annotateMerge(OpenApi.annotations({
|
|
35
|
+
identifier: "v2.pty.create",
|
|
36
|
+
summary: "Create PTY session",
|
|
37
|
+
description: "Create a pseudo-terminal session for a location.",
|
|
38
|
+
})))
|
|
39
|
+
.add(HttpApiEndpoint.get("pty.get", "/api/pty/:ptyID", {
|
|
40
|
+
params: { ptyID: Pty.ID },
|
|
41
|
+
query: LocationQuery,
|
|
42
|
+
success: Location.response(Pty.Info),
|
|
43
|
+
error: PtyNotFoundError,
|
|
44
|
+
})
|
|
45
|
+
.annotateMerge(locationQueryOpenApi)
|
|
46
|
+
.annotateMerge(OpenApi.annotations({
|
|
47
|
+
identifier: "v2.pty.get",
|
|
48
|
+
summary: "Get PTY session",
|
|
49
|
+
description: "Get one PTY session, including its exit code once exited.",
|
|
50
|
+
})))
|
|
51
|
+
.add(HttpApiEndpoint.put("pty.update", "/api/pty/:ptyID", {
|
|
52
|
+
params: { ptyID: Pty.ID },
|
|
53
|
+
query: LocationQuery,
|
|
54
|
+
payload: Pty.UpdateInput,
|
|
55
|
+
success: Location.response(Pty.Info),
|
|
56
|
+
error: PtyNotFoundError,
|
|
57
|
+
})
|
|
58
|
+
.annotateMerge(locationQueryOpenApi)
|
|
59
|
+
.annotateMerge(OpenApi.annotations({
|
|
60
|
+
identifier: "v2.pty.update",
|
|
61
|
+
summary: "Update PTY session",
|
|
62
|
+
description: "Update the title or viewport size of one PTY session.",
|
|
63
|
+
})))
|
|
64
|
+
.add(HttpApiEndpoint.delete("pty.remove", "/api/pty/:ptyID", {
|
|
65
|
+
params: { ptyID: Pty.ID },
|
|
66
|
+
query: LocationQuery,
|
|
67
|
+
success: HttpApiSchema.NoContent,
|
|
68
|
+
error: PtyNotFoundError,
|
|
69
|
+
})
|
|
70
|
+
.annotateMerge(locationQueryOpenApi)
|
|
71
|
+
.annotateMerge(OpenApi.annotations({
|
|
72
|
+
identifier: "v2.pty.remove",
|
|
73
|
+
summary: "Remove PTY session",
|
|
74
|
+
description: "Terminate and remove one PTY session.",
|
|
75
|
+
})))
|
|
76
|
+
.add(HttpApiEndpoint.post("pty.connectToken", "/api/pty/:ptyID/connect-token", {
|
|
77
|
+
params: { ptyID: Pty.ID },
|
|
78
|
+
query: LocationQuery,
|
|
79
|
+
success: Location.response(PtyTicket.ConnectToken),
|
|
80
|
+
error: [ForbiddenError, PtyNotFoundError],
|
|
81
|
+
})
|
|
82
|
+
.annotateMerge(locationQueryOpenApi)
|
|
83
|
+
.annotateMerge(OpenApi.annotations({
|
|
84
|
+
identifier: "v2.pty.connect.token",
|
|
85
|
+
summary: "Create PTY WebSocket token",
|
|
86
|
+
description: "Create a short-lived single-use ticket for opening a PTY WebSocket connection.",
|
|
87
|
+
})))
|
|
88
|
+
.add(
|
|
89
|
+
// Query fields are decoded in the raw handler after the existence check so a missing
|
|
90
|
+
// session responds with an empty 404 before any upgrade work.
|
|
91
|
+
HttpApiEndpoint.get("pty.connect", "/api/pty/:ptyID/connect", {
|
|
92
|
+
params: { ptyID: Pty.ID },
|
|
93
|
+
success: Schema.Boolean,
|
|
94
|
+
error: [ForbiddenError, PtyNotFoundError],
|
|
95
|
+
}).annotateMerge(OpenApi.annotations({
|
|
96
|
+
identifier: "v2.pty.connect",
|
|
97
|
+
summary: "Connect to PTY session",
|
|
98
|
+
description: "Establish a WebSocket connection streaming PTY output and accepting terminal input.",
|
|
99
|
+
transform: (operation) => ({
|
|
100
|
+
...operation,
|
|
101
|
+
"x-websocket": true,
|
|
102
|
+
parameters: [
|
|
103
|
+
...(operation.parameters ?? []),
|
|
104
|
+
...["location[directory]", "location[workspace]", "cursor", PTY_CONNECT_TICKET_QUERY].map((name) => ({
|
|
105
|
+
in: "query",
|
|
106
|
+
name,
|
|
107
|
+
schema: { type: "string" },
|
|
108
|
+
})),
|
|
109
|
+
],
|
|
110
|
+
}),
|
|
111
|
+
})))
|
|
112
|
+
.annotateMerge(OpenApi.annotations({ title: "pty", description: "Experimental location-scoped PTY routes." }));
|
|
@@ -0,0 +1,29 @@
|
|
|
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 ReferenceGroup: HttpApiGroup.HttpApiGroup<"server.reference", HttpApiEndpoint.HttpApiEndpoint<"reference.list", "GET", "/api/reference", never, Schema.toCodecStringTree<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
|
+
}>>, never, never, Schema.toCodecJson<Schema.Struct<{
|
|
10
|
+
readonly location: typeof Location.Info;
|
|
11
|
+
readonly data: Schema.$Array<Schema.Struct<{
|
|
12
|
+
readonly name: Schema.String;
|
|
13
|
+
readonly path: Schema.brand<Schema.String, "AbsolutePath">;
|
|
14
|
+
readonly description: Schema.decodeTo<Schema.optional<Schema.toType<Schema.String>>, Schema.optionalKey<Schema.String>, never, never>;
|
|
15
|
+
readonly hidden: Schema.decodeTo<Schema.optional<Schema.toType<Schema.Boolean>>, Schema.optionalKey<Schema.Boolean>, never, never>;
|
|
16
|
+
readonly source: Schema.Union<readonly [Schema.Struct<{
|
|
17
|
+
readonly type: Schema.Literal<"local">;
|
|
18
|
+
readonly path: Schema.brand<Schema.String, "AbsolutePath">;
|
|
19
|
+
readonly description: Schema.decodeTo<Schema.optional<Schema.toType<Schema.String>>, Schema.optionalKey<Schema.String>, never, never>;
|
|
20
|
+
readonly hidden: Schema.decodeTo<Schema.optional<Schema.toType<Schema.Boolean>>, Schema.optionalKey<Schema.Boolean>, never, never>;
|
|
21
|
+
}>, Schema.Struct<{
|
|
22
|
+
readonly type: Schema.Literal<"git">;
|
|
23
|
+
readonly repository: Schema.String;
|
|
24
|
+
readonly branch: Schema.decodeTo<Schema.optional<Schema.toType<Schema.String>>, Schema.optionalKey<Schema.String>, never, never>;
|
|
25
|
+
readonly description: Schema.decodeTo<Schema.optional<Schema.toType<Schema.String>>, Schema.optionalKey<Schema.String>, never, never>;
|
|
26
|
+
readonly hidden: Schema.decodeTo<Schema.optional<Schema.toType<Schema.Boolean>>, Schema.optionalKey<Schema.Boolean>, never, never>;
|
|
27
|
+
}>]>;
|
|
28
|
+
}>>;
|
|
29
|
+
}>>, never, never, never>, false>;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Location } from "@opencode-ai/schema/location";
|
|
2
|
+
import { Reference } from "@opencode-ai/schema/reference";
|
|
3
|
+
import { Schema } from "effect";
|
|
4
|
+
import { HttpApiEndpoint, HttpApiGroup, OpenApi } from "effect/unstable/httpapi";
|
|
5
|
+
import { LocationQuery, locationQueryOpenApi } from "./location.js";
|
|
6
|
+
export const ReferenceGroup = HttpApiGroup.make("server.reference")
|
|
7
|
+
.add(HttpApiEndpoint.get("reference.list", "/api/reference", {
|
|
8
|
+
query: LocationQuery,
|
|
9
|
+
success: Location.response(Schema.Array(Reference.Info)),
|
|
10
|
+
})
|
|
11
|
+
.annotateMerge(locationQueryOpenApi)
|
|
12
|
+
.annotateMerge(OpenApi.annotations({
|
|
13
|
+
identifier: "v2.reference.list",
|
|
14
|
+
summary: "List references",
|
|
15
|
+
description: "List references available in the requested location.",
|
|
16
|
+
})))
|
|
17
|
+
.annotateMerge(OpenApi.annotations({
|
|
18
|
+
title: "reference",
|
|
19
|
+
description: "Location-scoped project references.",
|
|
20
|
+
}));
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { Schema } from "effect";
|
|
2
|
+
import { HttpApiEndpoint, HttpApiGroup } from "effect/unstable/httpapi";
|
|
3
|
+
export declare const ServerGroup: HttpApiGroup.HttpApiGroup<"server.server", HttpApiEndpoint.HttpApiEndpoint<"server.get", "GET", "/api/server", never, never, never, never, Schema.toCodecJson<Schema.Struct<{
|
|
4
|
+
readonly urls: Schema.$Array<Schema.String>;
|
|
5
|
+
}>>, never, never, never>, false>;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Schema } from "effect";
|
|
2
|
+
import { HttpApiEndpoint, HttpApiGroup, OpenApi } from "effect/unstable/httpapi";
|
|
3
|
+
export const ServerGroup = HttpApiGroup.make("server.server")
|
|
4
|
+
.add(HttpApiEndpoint.get("server.get", "/api/server", {
|
|
5
|
+
success: Schema.Struct({ urls: Schema.Array(Schema.String) }),
|
|
6
|
+
}).annotateMerge(OpenApi.annotations({
|
|
7
|
+
identifier: "v2.server.get",
|
|
8
|
+
summary: "Get server information",
|
|
9
|
+
description: "Return the URLs that can be used to connect to this server.",
|
|
10
|
+
})))
|
|
11
|
+
.annotateMerge(OpenApi.annotations({ title: "server" }));
|