@opencode-cockpit/protocol 0.1.3 → 0.1.5

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/src/daemon.ts DELETED
@@ -1,48 +0,0 @@
1
- import { z } from "zod"
2
- import { method } from "./contract.ts"
3
-
4
- export const ClientInfo = z.object({
5
- name: z.string().min(1),
6
- version: z.string().min(1),
7
- pid: z.number().int().optional(),
8
- })
9
-
10
- export const Version = z.object({ major: z.number().int(), minor: z.number().int() })
11
-
12
- export const HelloResult = z.object({
13
- daemonVersion: z.string(),
14
- /** Content identity of the running daemon code (see daemonBuildId). */
15
- build: z.string().optional(),
16
- protocol: Version,
17
- modules: z.array(z.string()),
18
- pid: z.number().int(),
19
- startedAt: z.number(),
20
- })
21
-
22
- export const StatusResult = z.object({
23
- pid: z.number().int(),
24
- uptimeMs: z.number(),
25
- clients: z.number().int(),
26
- modules: z.array(z.object({ name: z.string(), busy: z.boolean() })),
27
- })
28
-
29
- export const daemonContract = {
30
- "daemon.hello": method(z.object({ client: ClientInfo, protocol: Version }), HelloResult),
31
- "daemon.status": method(z.object({}).optional(), StatusResult),
32
- "daemon.shutdown": method(
33
- z.object({ force: z.boolean().optional() }).optional(),
34
- z.object({ accepted: z.boolean() }),
35
- ),
36
- "events.subscribe": method(
37
- z.object({ topics: z.array(z.string().min(1)).min(1) }),
38
- z.object({ topics: z.array(z.string()) }),
39
- ),
40
- "events.unsubscribe": method(
41
- z.object({ topics: z.array(z.string().min(1)).min(1) }),
42
- z.object({ topics: z.array(z.string()) }),
43
- ),
44
- }
45
-
46
- export type HelloResult = z.output<typeof HelloResult>
47
- export type StatusResult = z.output<typeof StatusResult>
48
- export type ClientInfo = z.output<typeof ClientInfo>
package/src/framing.ts DELETED
@@ -1,26 +0,0 @@
1
- /** NDJSON framing shared by daemon and client. */
2
-
3
- const encoder = new TextEncoder()
4
-
5
- export function encodeFrame(message: unknown): Uint8Array {
6
- return encoder.encode(`${JSON.stringify(message)}\n`)
7
- }
8
-
9
- /** Accumulates chunks and yields complete lines. Bounded to protect against runaway peers. */
10
- export class LineDecoder {
11
- private readonly decoder = new TextDecoder()
12
- private pending = ""
13
-
14
- constructor(private readonly maxLineBytes = 16 * 1024 * 1024) {}
15
-
16
- push(chunk: Uint8Array): string[] {
17
- this.pending += this.decoder.decode(chunk, { stream: true })
18
- const parts = this.pending.split("\n")
19
- this.pending = parts.pop() ?? ""
20
- if (this.pending.length > this.maxLineBytes) {
21
- this.pending = ""
22
- throw new Error(`frame exceeds ${this.maxLineBytes} bytes`)
23
- }
24
- return parts.filter((line) => line.length > 0)
25
- }
26
- }
package/src/index.ts DELETED
@@ -1,21 +0,0 @@
1
- import type { EventContract } from "./contract.ts"
2
- import { daemonContract } from "./daemon.ts"
3
- import { shellContract, shellEvents } from "./shell.ts"
4
-
5
- export * from "./build.ts"
6
- export * from "./contract.ts"
7
- export * from "./daemon.ts"
8
- export * from "./framing.ts"
9
- export * from "./paths.ts"
10
- export * from "./rpc.ts"
11
- export * as shell from "./shell.ts"
12
-
13
- /** Every method the daemon serves. Adding a module means spreading its contract here. */
14
- export const contract = { ...daemonContract, ...shellContract }
15
- export type Methods = typeof contract
16
- export type MethodName = keyof Methods
17
-
18
- /** Every event topic the daemon emits. */
19
- export const events = { ...shellEvents } satisfies EventContract
20
- export type Events = typeof events
21
- export type Topic = keyof Events
package/src/paths.ts DELETED
@@ -1,25 +0,0 @@
1
- import { homedir } from "node:os"
2
- import { join } from "node:path"
3
-
4
- export interface CockpitPaths {
5
- home: string
6
- socket: string
7
- pidFile: string
8
- lockFile: string
9
- logFile: string
10
- }
11
-
12
- /**
13
- * Filesystem layout shared by daemon and clients. Pure: creates nothing.
14
- * Kept short because unix socket paths are limited to 104 bytes on macOS.
15
- */
16
- export function resolvePaths(env: Record<string, string | undefined> = process.env): CockpitPaths {
17
- const home = env.COCKPIT_HOME ?? join(env.XDG_CACHE_HOME ?? join(homedir(), ".cache"), "opencode-cockpit")
18
- return {
19
- home,
20
- socket: join(home, "cockpitd.sock"),
21
- pidFile: join(home, "cockpitd.pid"),
22
- lockFile: join(home, "spawn.lock"),
23
- logFile: join(home, "cockpitd.log"),
24
- }
25
- }
package/src/rpc.ts DELETED
@@ -1,96 +0,0 @@
1
- /** Wire envelope: JSON-RPC 2.0, one JSON object per line (ADR 0002). */
2
-
3
- /** Bump MAJOR on breaking changes to methods, events or framing. */
4
- export const PROTOCOL_VERSION = { major: 1, minor: 1 } as const
5
-
6
- export type RequestId = number | string
7
-
8
- export interface RpcRequest {
9
- jsonrpc: "2.0"
10
- id: RequestId
11
- method: string
12
- params?: unknown
13
- }
14
-
15
- export interface RpcNotification {
16
- jsonrpc: "2.0"
17
- method: string
18
- params?: unknown
19
- }
20
-
21
- export interface RpcSuccess {
22
- jsonrpc: "2.0"
23
- id: RequestId
24
- result: unknown
25
- }
26
-
27
- export interface RpcFailure {
28
- jsonrpc: "2.0"
29
- id: RequestId | null
30
- error: RpcErrorShape
31
- }
32
-
33
- export type RpcMessage = RpcRequest | RpcNotification | RpcSuccess | RpcFailure
34
-
35
- export interface RpcErrorShape {
36
- code: number
37
- message: string
38
- data?: unknown
39
- }
40
-
41
- export const ErrorCode = {
42
- ParseError: -32700,
43
- InvalidRequest: -32600,
44
- MethodNotFound: -32601,
45
- InvalidParams: -32602,
46
- InternalError: -32603,
47
- // Application range
48
- NotFound: -32001,
49
- InvalidState: -32002,
50
- ProtocolMismatch: -32003,
51
- SpawnFailed: -32004,
52
- ShuttingDown: -32005,
53
- } as const
54
-
55
- export type ErrorCodeValue = (typeof ErrorCode)[keyof typeof ErrorCode]
56
-
57
- export class RpcError extends Error {
58
- constructor(
59
- readonly code: number,
60
- message: string,
61
- readonly data?: unknown,
62
- ) {
63
- super(message)
64
- this.name = "RpcError"
65
- }
66
-
67
- toShape(): RpcErrorShape {
68
- return this.data === undefined
69
- ? { code: this.code, message: this.message }
70
- : { code: this.code, message: this.message, data: this.data }
71
- }
72
-
73
- static from(shape: RpcErrorShape): RpcError {
74
- return new RpcError(shape.code, shape.message, shape.data)
75
- }
76
- }
77
-
78
- /** Method name for daemon → client notifications. */
79
- export const EVENT_METHOD = "event"
80
-
81
- export interface EventEnvelope<T extends string = string, D = unknown> {
82
- topic: T
83
- data: D
84
- }
85
-
86
- export function isRequest(msg: RpcMessage): msg is RpcRequest {
87
- return "method" in msg && "id" in msg && msg.id !== undefined
88
- }
89
-
90
- export function isNotification(msg: RpcMessage): msg is RpcNotification {
91
- return "method" in msg && !("id" in msg)
92
- }
93
-
94
- export function isResponse(msg: RpcMessage): msg is RpcSuccess | RpcFailure {
95
- return !("method" in msg) && ("result" in msg || "error" in msg)
96
- }