@cluesmith/codev 2.0.0-rc.69 → 2.0.0-rc.70

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 (139) hide show
  1. package/dashboard/dist/assets/{index-CG7nUttd.js → index-CDAINZKT.js} +21 -21
  2. package/dashboard/dist/assets/{index-CG7nUttd.js.map → index-CDAINZKT.js.map} +1 -1
  3. package/dashboard/dist/index.html +1 -1
  4. package/dist/agent-farm/cli.js +2 -2
  5. package/dist/agent-farm/cli.js.map +1 -1
  6. package/dist/agent-farm/commands/architect.d.ts +3 -3
  7. package/dist/agent-farm/commands/architect.d.ts.map +1 -1
  8. package/dist/agent-farm/commands/architect.js +20 -142
  9. package/dist/agent-farm/commands/architect.js.map +1 -1
  10. package/dist/agent-farm/commands/attach.d.ts.map +1 -1
  11. package/dist/agent-farm/commands/attach.js +13 -50
  12. package/dist/agent-farm/commands/attach.js.map +1 -1
  13. package/dist/agent-farm/commands/cleanup.d.ts.map +1 -1
  14. package/dist/agent-farm/commands/cleanup.js +1 -11
  15. package/dist/agent-farm/commands/cleanup.js.map +1 -1
  16. package/dist/agent-farm/commands/send.d.ts +1 -1
  17. package/dist/agent-farm/commands/send.d.ts.map +1 -1
  18. package/dist/agent-farm/commands/send.js +35 -92
  19. package/dist/agent-farm/commands/send.js.map +1 -1
  20. package/dist/agent-farm/commands/spawn.d.ts.map +1 -1
  21. package/dist/agent-farm/commands/spawn.js +26 -58
  22. package/dist/agent-farm/commands/spawn.js.map +1 -1
  23. package/dist/agent-farm/commands/status.js +1 -1
  24. package/dist/agent-farm/commands/status.js.map +1 -1
  25. package/dist/agent-farm/commands/stop.d.ts.map +1 -1
  26. package/dist/agent-farm/commands/stop.js +9 -44
  27. package/dist/agent-farm/commands/stop.js.map +1 -1
  28. package/dist/agent-farm/commands/tower-cloud.d.ts.map +1 -1
  29. package/dist/agent-farm/commands/tower-cloud.js +18 -1
  30. package/dist/agent-farm/commands/tower-cloud.js.map +1 -1
  31. package/dist/agent-farm/db/index.d.ts.map +1 -1
  32. package/dist/agent-farm/db/index.js +61 -0
  33. package/dist/agent-farm/db/index.js.map +1 -1
  34. package/dist/agent-farm/db/migrate.d.ts.map +1 -1
  35. package/dist/agent-farm/db/migrate.js +6 -9
  36. package/dist/agent-farm/db/migrate.js.map +1 -1
  37. package/dist/agent-farm/db/schema.d.ts +2 -2
  38. package/dist/agent-farm/db/schema.d.ts.map +1 -1
  39. package/dist/agent-farm/db/schema.js +3 -4
  40. package/dist/agent-farm/db/schema.js.map +1 -1
  41. package/dist/agent-farm/db/types.d.ts +0 -3
  42. package/dist/agent-farm/db/types.d.ts.map +1 -1
  43. package/dist/agent-farm/db/types.js +0 -3
  44. package/dist/agent-farm/db/types.js.map +1 -1
  45. package/dist/agent-farm/lib/tower-client.d.ts +4 -0
  46. package/dist/agent-farm/lib/tower-client.d.ts.map +1 -1
  47. package/dist/agent-farm/lib/tower-client.js +10 -0
  48. package/dist/agent-farm/lib/tower-client.js.map +1 -1
  49. package/dist/agent-farm/lib/tunnel-client.d.ts.map +1 -1
  50. package/dist/agent-farm/lib/tunnel-client.js +6 -13
  51. package/dist/agent-farm/lib/tunnel-client.js.map +1 -1
  52. package/dist/agent-farm/servers/tower-server.js +482 -494
  53. package/dist/agent-farm/servers/tower-server.js.map +1 -1
  54. package/dist/agent-farm/state.d.ts.map +1 -1
  55. package/dist/agent-farm/state.js +6 -10
  56. package/dist/agent-farm/state.js.map +1 -1
  57. package/dist/agent-farm/types.d.ts +0 -7
  58. package/dist/agent-farm/types.d.ts.map +1 -1
  59. package/dist/agent-farm/utils/deps.d.ts.map +1 -1
  60. package/dist/agent-farm/utils/deps.js +0 -16
  61. package/dist/agent-farm/utils/deps.js.map +1 -1
  62. package/dist/agent-farm/utils/gate-watcher.js +4 -4
  63. package/dist/agent-farm/utils/gate-watcher.js.map +1 -1
  64. package/dist/agent-farm/utils/session.d.ts +6 -6
  65. package/dist/agent-farm/utils/session.d.ts.map +1 -1
  66. package/dist/agent-farm/utils/session.js +4 -4
  67. package/dist/agent-farm/utils/session.js.map +1 -1
  68. package/dist/agent-farm/utils/shell.d.ts +4 -4
  69. package/dist/agent-farm/utils/shell.js +4 -4
  70. package/dist/cli.d.ts.map +1 -1
  71. package/dist/cli.js +2 -0
  72. package/dist/cli.js.map +1 -1
  73. package/dist/commands/consult/index.d.ts +1 -0
  74. package/dist/commands/consult/index.d.ts.map +1 -1
  75. package/dist/commands/consult/index.js +19 -5
  76. package/dist/commands/consult/index.js.map +1 -1
  77. package/dist/commands/doctor.d.ts.map +1 -1
  78. package/dist/commands/doctor.js +0 -12
  79. package/dist/commands/doctor.js.map +1 -1
  80. package/dist/commands/porch/next.d.ts.map +1 -1
  81. package/dist/commands/porch/next.js +90 -8
  82. package/dist/commands/porch/next.js.map +1 -1
  83. package/dist/commands/porch/prompts.d.ts.map +1 -1
  84. package/dist/commands/porch/prompts.js +26 -4
  85. package/dist/commands/porch/prompts.js.map +1 -1
  86. package/dist/commands/porch/verdict.d.ts +0 -8
  87. package/dist/commands/porch/verdict.d.ts.map +1 -1
  88. package/dist/commands/porch/verdict.js +0 -13
  89. package/dist/commands/porch/verdict.js.map +1 -1
  90. package/dist/terminal/pty-manager.d.ts +9 -0
  91. package/dist/terminal/pty-manager.d.ts.map +1 -1
  92. package/dist/terminal/pty-manager.js +45 -2
  93. package/dist/terminal/pty-manager.js.map +1 -1
  94. package/dist/terminal/pty-session.d.ts +27 -4
  95. package/dist/terminal/pty-session.d.ts.map +1 -1
  96. package/dist/terminal/pty-session.js +112 -4
  97. package/dist/terminal/pty-session.js.map +1 -1
  98. package/dist/terminal/ring-buffer.d.ts +10 -3
  99. package/dist/terminal/ring-buffer.d.ts.map +1 -1
  100. package/dist/terminal/ring-buffer.js +25 -5
  101. package/dist/terminal/ring-buffer.js.map +1 -1
  102. package/dist/terminal/session-manager.d.ts +115 -0
  103. package/dist/terminal/session-manager.d.ts.map +1 -0
  104. package/dist/terminal/session-manager.js +582 -0
  105. package/dist/terminal/session-manager.js.map +1 -0
  106. package/dist/terminal/shepherd-client.d.ts +58 -0
  107. package/dist/terminal/shepherd-client.d.ts.map +1 -0
  108. package/dist/terminal/shepherd-client.js +212 -0
  109. package/dist/terminal/shepherd-client.js.map +1 -0
  110. package/dist/terminal/shepherd-main.d.ts +19 -0
  111. package/dist/terminal/shepherd-main.d.ts.map +1 -0
  112. package/dist/terminal/shepherd-main.js +153 -0
  113. package/dist/terminal/shepherd-main.js.map +1 -0
  114. package/dist/terminal/shepherd-process.d.ts +75 -0
  115. package/dist/terminal/shepherd-process.d.ts.map +1 -0
  116. package/dist/terminal/shepherd-process.js +279 -0
  117. package/dist/terminal/shepherd-process.js.map +1 -0
  118. package/dist/terminal/shepherd-protocol.d.ts +115 -0
  119. package/dist/terminal/shepherd-protocol.d.ts.map +1 -0
  120. package/dist/terminal/shepherd-protocol.js +214 -0
  121. package/dist/terminal/shepherd-protocol.js.map +1 -0
  122. package/dist/terminal/shepherd-replay-buffer.d.ts +38 -0
  123. package/dist/terminal/shepherd-replay-buffer.d.ts.map +1 -0
  124. package/dist/terminal/shepherd-replay-buffer.js +94 -0
  125. package/dist/terminal/shepherd-replay-buffer.js.map +1 -0
  126. package/package.json +1 -1
  127. package/skeleton/.claude/skills/codev/SKILL.md +1 -1
  128. package/skeleton/DEPENDENCIES.md +2 -34
  129. package/skeleton/consult-types/impl-review.md +9 -9
  130. package/skeleton/consult-types/integration-review.md +1 -1
  131. package/skeleton/consult-types/plan-review.md +1 -1
  132. package/skeleton/consult-types/pr-ready.md +1 -1
  133. package/skeleton/consult-types/spec-review.md +1 -1
  134. package/skeleton/protocols/bugfix/prompts/pr.md +23 -4
  135. package/skeleton/protocols/maintain/protocol.md +3 -3
  136. package/skeleton/resources/commands/agent-farm.md +2 -3
  137. package/skeleton/resources/commands/codev.md +0 -2
  138. package/skeleton/roles/architect.md +1 -1
  139. package/skeleton/roles/consultant.md +6 -6
@@ -0,0 +1,279 @@
1
+ /**
2
+ * ShepherdProcess: the testable core logic of the shepherd daemon.
3
+ *
4
+ * Owns a single PTY via the IShepherdPty interface (injected for testability).
5
+ * Listens on a Unix socket for a single Tower connection. Handles the binary
6
+ * wire protocol: HELLO/WELCOME handshake, DATA forwarding, RESIZE, SIGNAL,
7
+ * SPAWN, PING/PONG, and EXIT lifecycle.
8
+ *
9
+ * The shepherd accepts only one Tower connection at a time. A new connection
10
+ * replaces the old one (handles rapid Tower restarts cleanly).
11
+ */
12
+ import fs from 'node:fs';
13
+ import net from 'node:net';
14
+ import { EventEmitter } from 'node:events';
15
+ import { FrameType, PROTOCOL_VERSION, ALLOWED_SIGNALS, createFrameParser, encodeData, encodeWelcome, encodeExit, encodeReplay, encodePong, parseJsonPayload, isKnownFrameType, } from './shepherd-protocol.js';
16
+ import { ShepherdReplayBuffer } from './shepherd-replay-buffer.js';
17
+ // --- ShepherdProcess ---
18
+ export class ShepherdProcess extends EventEmitter {
19
+ ptyFactory;
20
+ socketPath;
21
+ pty = null;
22
+ server = null;
23
+ currentConnection = null;
24
+ replayBuffer;
25
+ cols = 80;
26
+ rows = 24;
27
+ startTime = Date.now();
28
+ exited = false;
29
+ constructor(ptyFactory, socketPath, replayBufferLines = 10_000) {
30
+ super();
31
+ this.ptyFactory = ptyFactory;
32
+ this.socketPath = socketPath;
33
+ this.replayBuffer = new ShepherdReplayBuffer(replayBufferLines);
34
+ }
35
+ /**
36
+ * Start the shepherd: spawn the PTY and begin listening on the Unix socket.
37
+ */
38
+ async start(command, args, cwd, env, cols, rows) {
39
+ this.cols = cols;
40
+ this.rows = rows;
41
+ this.startTime = Date.now();
42
+ this.spawnPty(command, args, cwd, env, cols, rows);
43
+ await this.listen();
44
+ }
45
+ spawnPty(command, args, cwd, env, cols, rows) {
46
+ this.exited = false;
47
+ const pty = this.ptyFactory();
48
+ this.pty = pty;
49
+ pty.spawn(command, args, {
50
+ name: 'xterm-256color',
51
+ cols,
52
+ rows,
53
+ cwd,
54
+ env,
55
+ });
56
+ pty.onData((data) => {
57
+ // Guard: ignore data from a replaced PTY (after SPAWN)
58
+ if (this.pty !== pty)
59
+ return;
60
+ const buf = Buffer.from(data, 'utf-8');
61
+ this.replayBuffer.append(buf);
62
+ if (this.currentConnection && !this.currentConnection.destroyed) {
63
+ this.currentConnection.write(encodeData(buf));
64
+ }
65
+ });
66
+ pty.onExit((exitInfo) => {
67
+ // Guard: ignore exit from a replaced PTY (after SPAWN).
68
+ // Without this, the old PTY's exit would set this.exited = true
69
+ // and send an EXIT frame, corrupting the state of the new PTY.
70
+ if (this.pty !== pty)
71
+ return;
72
+ this.exited = true;
73
+ const exitFrame = encodeExit({
74
+ code: exitInfo.exitCode,
75
+ signal: exitInfo.signal != null ? String(exitInfo.signal) : null,
76
+ });
77
+ if (this.currentConnection && !this.currentConnection.destroyed) {
78
+ this.currentConnection.write(exitFrame);
79
+ }
80
+ this.emit('exit', exitInfo);
81
+ });
82
+ }
83
+ listen() {
84
+ return new Promise((resolve, reject) => {
85
+ this.server = net.createServer((socket) => {
86
+ this.handleConnection(socket);
87
+ });
88
+ this.server.on('error', (err) => {
89
+ this.emit('error', err);
90
+ reject(err);
91
+ });
92
+ this.server.listen(this.socketPath, () => {
93
+ // Enforce 0600 permissions on socket file (owner-only access).
94
+ // Unix sockets inherit permissions from umask; we override after creation.
95
+ try {
96
+ fs.chmodSync(this.socketPath, 0o600);
97
+ }
98
+ catch {
99
+ // Non-fatal: socket still works, just with default permissions
100
+ }
101
+ resolve();
102
+ });
103
+ });
104
+ }
105
+ /**
106
+ * Handle an incoming Tower connection. Only one connection is active at a
107
+ * time — a new connection closes the previous one.
108
+ */
109
+ handleConnection(socket) {
110
+ // Close previous connection if any
111
+ if (this.currentConnection && !this.currentConnection.destroyed) {
112
+ this.currentConnection.destroy();
113
+ }
114
+ this.currentConnection = socket;
115
+ const parser = createFrameParser();
116
+ socket.pipe(parser);
117
+ parser.on('data', (frame) => {
118
+ this.handleFrame(socket, frame);
119
+ });
120
+ parser.on('error', (err) => {
121
+ this.emit('protocol-error', err);
122
+ socket.destroy();
123
+ });
124
+ socket.on('close', () => {
125
+ if (this.currentConnection === socket) {
126
+ this.currentConnection = null;
127
+ }
128
+ });
129
+ socket.on('error', () => {
130
+ if (this.currentConnection === socket) {
131
+ this.currentConnection = null;
132
+ }
133
+ });
134
+ }
135
+ handleFrame(socket, frame) {
136
+ if (!isKnownFrameType(frame.type)) {
137
+ // Unknown frame types are silently ignored (forward compatibility)
138
+ return;
139
+ }
140
+ switch (frame.type) {
141
+ case FrameType.HELLO:
142
+ this.handleHello(socket, frame.payload);
143
+ break;
144
+ case FrameType.DATA:
145
+ this.handleData(frame.payload);
146
+ break;
147
+ case FrameType.RESIZE:
148
+ this.handleResize(socket, frame.payload);
149
+ break;
150
+ case FrameType.SIGNAL:
151
+ this.handleSignal(socket, frame.payload);
152
+ break;
153
+ case FrameType.SPAWN:
154
+ this.handleSpawn(socket, frame.payload);
155
+ break;
156
+ case FrameType.PING:
157
+ socket.write(encodePong());
158
+ break;
159
+ case FrameType.PONG:
160
+ // No-op: keepalive acknowledgement
161
+ break;
162
+ // Shepherd doesn't expect REPLAY, EXIT, WELCOME from Tower
163
+ default:
164
+ break;
165
+ }
166
+ }
167
+ handleHello(socket, payload) {
168
+ try {
169
+ const hello = parseJsonPayload(payload);
170
+ this.emit('hello', hello);
171
+ }
172
+ catch {
173
+ this.emit('protocol-error', new Error('Invalid HELLO payload'));
174
+ socket.destroy();
175
+ return;
176
+ }
177
+ // Send WELCOME response
178
+ const welcome = encodeWelcome({
179
+ version: PROTOCOL_VERSION,
180
+ pid: this.pty?.pid ?? -1,
181
+ cols: this.cols,
182
+ rows: this.rows,
183
+ startTime: this.startTime,
184
+ });
185
+ socket.write(welcome);
186
+ // Send replay buffer
187
+ const replayData = this.replayBuffer.getReplayData();
188
+ if (replayData.length > 0) {
189
+ socket.write(encodeReplay(replayData));
190
+ }
191
+ }
192
+ handleData(payload) {
193
+ if (this.pty && !this.exited) {
194
+ this.pty.write(payload.toString('utf-8'));
195
+ }
196
+ }
197
+ handleResize(socket, payload) {
198
+ try {
199
+ const msg = parseJsonPayload(payload);
200
+ this.cols = msg.cols;
201
+ this.rows = msg.rows;
202
+ if (this.pty && !this.exited) {
203
+ this.pty.resize(msg.cols, msg.rows);
204
+ }
205
+ }
206
+ catch {
207
+ this.emit('protocol-error', new Error('Invalid RESIZE payload'));
208
+ socket.destroy();
209
+ }
210
+ }
211
+ handleSignal(socket, payload) {
212
+ try {
213
+ const msg = parseJsonPayload(payload);
214
+ if (!ALLOWED_SIGNALS.has(msg.signal)) {
215
+ this.emit('protocol-error', new Error(`Signal ${msg.signal} not in allowlist`));
216
+ return;
217
+ }
218
+ if (this.pty && !this.exited) {
219
+ this.pty.kill(msg.signal);
220
+ }
221
+ }
222
+ catch {
223
+ this.emit('protocol-error', new Error('Invalid SIGNAL payload'));
224
+ socket.destroy();
225
+ }
226
+ }
227
+ handleSpawn(socket, payload) {
228
+ try {
229
+ const msg = parseJsonPayload(payload);
230
+ // Kill old PTY if still alive
231
+ if (this.pty && !this.exited) {
232
+ this.pty.kill(15); // SIGTERM
233
+ }
234
+ // Clear replay buffer for fresh session
235
+ this.replayBuffer.clear();
236
+ // Spawn new PTY
237
+ this.spawnPty(msg.command, msg.args, msg.cwd, msg.env, this.cols, this.rows);
238
+ this.emit('spawn', msg);
239
+ }
240
+ catch {
241
+ this.emit('protocol-error', new Error('Invalid SPAWN payload'));
242
+ socket.destroy();
243
+ }
244
+ }
245
+ /** Get the current replay buffer data. */
246
+ getReplayData() {
247
+ return this.replayBuffer.getReplayData();
248
+ }
249
+ /** Get the process start time (epoch ms). */
250
+ getStartTime() {
251
+ return this.startTime;
252
+ }
253
+ /** Get the current PTY PID. */
254
+ getPid() {
255
+ return this.pty?.pid ?? -1;
256
+ }
257
+ /** Whether the child process has exited. */
258
+ get hasExited() {
259
+ return this.exited;
260
+ }
261
+ /**
262
+ * Graceful shutdown: kill child process, close socket server, clean up.
263
+ */
264
+ shutdown() {
265
+ if (this.pty && !this.exited) {
266
+ this.pty.kill(15); // SIGTERM
267
+ }
268
+ if (this.currentConnection && !this.currentConnection.destroyed) {
269
+ this.currentConnection.destroy();
270
+ }
271
+ this.currentConnection = null;
272
+ if (this.server) {
273
+ this.server.close();
274
+ this.server = null;
275
+ }
276
+ this.emit('shutdown');
277
+ }
278
+ }
279
+ //# sourceMappingURL=shepherd-process.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shepherd-process.js","sourceRoot":"","sources":["../../src/terminal/shepherd-process.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,115 @@
1
+ /**
2
+ * Shepherd wire protocol: binary frame encoding/decoding for Unix socket
3
+ * communication between Tower and shepherd processes.
4
+ *
5
+ * Frame format: [1-byte type] [4-byte big-endian length] [payload]
6
+ *
7
+ * This module is imported by both the shepherd process (standalone) and
8
+ * Tower (within the main package). It has NO dependencies beyond Node.js
9
+ * built-ins to keep the shepherd process lightweight.
10
+ */
11
+ import { Transform, type TransformCallback } from 'node:stream';
12
+ export declare const FrameType: {
13
+ readonly DATA: 1;
14
+ readonly RESIZE: 2;
15
+ readonly SIGNAL: 3;
16
+ readonly EXIT: 4;
17
+ readonly REPLAY: 5;
18
+ readonly PING: 6;
19
+ readonly PONG: 7;
20
+ readonly HELLO: 8;
21
+ readonly WELCOME: 9;
22
+ readonly SPAWN: 10;
23
+ };
24
+ export type FrameTypeValue = (typeof FrameType)[keyof typeof FrameType];
25
+ export declare const PROTOCOL_VERSION = 1;
26
+ export declare const MAX_FRAME_SIZE: number;
27
+ export declare const HEADER_SIZE = 5;
28
+ export declare const ALLOWED_SIGNALS: Set<number>;
29
+ export interface ResizeMessage {
30
+ cols: number;
31
+ rows: number;
32
+ }
33
+ export interface SignalMessage {
34
+ signal: number;
35
+ }
36
+ export interface ExitMessage {
37
+ code: number | null;
38
+ signal: string | null;
39
+ }
40
+ export interface HelloMessage {
41
+ version: number;
42
+ }
43
+ export interface WelcomeMessage {
44
+ version: number;
45
+ pid: number;
46
+ cols: number;
47
+ rows: number;
48
+ startTime: number;
49
+ }
50
+ export interface SpawnMessage {
51
+ command: string;
52
+ args: string[];
53
+ cwd: string;
54
+ env: Record<string, string>;
55
+ }
56
+ /**
57
+ * Encode a frame with the given type and payload.
58
+ */
59
+ export declare function encodeFrame(type: FrameTypeValue, payload: Buffer): Buffer;
60
+ /** Encode a DATA frame (raw PTY bytes). */
61
+ export declare function encodeData(data: Buffer | string): Buffer;
62
+ /** Encode a RESIZE frame. */
63
+ export declare function encodeResize(msg: ResizeMessage): Buffer;
64
+ /** Encode a SIGNAL frame. */
65
+ export declare function encodeSignal(msg: SignalMessage): Buffer;
66
+ /** Encode an EXIT frame. */
67
+ export declare function encodeExit(msg: ExitMessage): Buffer;
68
+ /** Encode a REPLAY frame (raw bytes). */
69
+ export declare function encodeReplay(data: Buffer): Buffer;
70
+ /** Encode a PING frame. */
71
+ export declare function encodePing(): Buffer;
72
+ /** Encode a PONG frame. */
73
+ export declare function encodePong(): Buffer;
74
+ /** Encode a HELLO frame. */
75
+ export declare function encodeHello(msg: HelloMessage): Buffer;
76
+ /** Encode a WELCOME frame. */
77
+ export declare function encodeWelcome(msg: WelcomeMessage): Buffer;
78
+ /** Encode a SPAWN frame. */
79
+ export declare function encodeSpawn(msg: SpawnMessage): Buffer;
80
+ export interface ParsedFrame {
81
+ type: FrameTypeValue | number;
82
+ payload: Buffer;
83
+ }
84
+ /**
85
+ * A Transform stream that parses the binary frame protocol.
86
+ *
87
+ * Input: raw socket data (may be fragmented across chunks)
88
+ * Output: ParsedFrame objects (in objectMode)
89
+ *
90
+ * Emits 'frame-error' event on protocol violations (oversized frames,
91
+ * malformed headers). The stream is destroyed on error.
92
+ */
93
+ export declare class FrameParser extends Transform {
94
+ private chunks;
95
+ private bufferedLength;
96
+ constructor();
97
+ _transform(chunk: Buffer, _encoding: BufferEncoding, callback: TransformCallback): void;
98
+ _flush(callback: TransformCallback): void;
99
+ private drainFrames;
100
+ private peek;
101
+ private consume;
102
+ }
103
+ /**
104
+ * Create a streaming frame parser.
105
+ * Convenience factory matching the plan's API.
106
+ */
107
+ export declare function createFrameParser(): FrameParser;
108
+ /** Check if a frame type is a known type. */
109
+ export declare function isKnownFrameType(type: number): type is FrameTypeValue;
110
+ /**
111
+ * Parse a JSON payload from a control frame.
112
+ * Throws on invalid JSON.
113
+ */
114
+ export declare function parseJsonPayload<T>(payload: Buffer): T;
115
+ //# sourceMappingURL=shepherd-protocol.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shepherd-protocol.d.ts","sourceRoot":"","sources":["../../src/terminal/shepherd-protocol.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,214 @@
1
+ /**
2
+ * Shepherd wire protocol: binary frame encoding/decoding for Unix socket
3
+ * communication between Tower and shepherd processes.
4
+ *
5
+ * Frame format: [1-byte type] [4-byte big-endian length] [payload]
6
+ *
7
+ * This module is imported by both the shepherd process (standalone) and
8
+ * Tower (within the main package). It has NO dependencies beyond Node.js
9
+ * built-ins to keep the shepherd process lightweight.
10
+ */
11
+ import { Transform } from 'node:stream';
12
+ // --- Frame Types ---
13
+ export const FrameType = {
14
+ DATA: 0x01,
15
+ RESIZE: 0x02,
16
+ SIGNAL: 0x03,
17
+ EXIT: 0x04,
18
+ REPLAY: 0x05,
19
+ PING: 0x06,
20
+ PONG: 0x07,
21
+ HELLO: 0x08,
22
+ WELCOME: 0x09,
23
+ SPAWN: 0x0a,
24
+ };
25
+ // --- Protocol Constants ---
26
+ export const PROTOCOL_VERSION = 1;
27
+ export const MAX_FRAME_SIZE = 16 * 1024 * 1024; // 16MB
28
+ export const HEADER_SIZE = 5; // 1 byte type + 4 bytes length
29
+ // --- Allowed Signals ---
30
+ export const ALLOWED_SIGNALS = new Set([
31
+ 1, // SIGHUP
32
+ 2, // SIGINT
33
+ 9, // SIGKILL
34
+ 15, // SIGTERM
35
+ 28, // SIGWINCH
36
+ ]);
37
+ // --- Frame Encoding ---
38
+ /**
39
+ * Encode a frame with the given type and payload.
40
+ */
41
+ export function encodeFrame(type, payload) {
42
+ const frame = Buffer.allocUnsafe(HEADER_SIZE + payload.length);
43
+ frame[0] = type;
44
+ frame.writeUInt32BE(payload.length, 1);
45
+ payload.copy(frame, HEADER_SIZE);
46
+ return frame;
47
+ }
48
+ /** Encode a DATA frame (raw PTY bytes). */
49
+ export function encodeData(data) {
50
+ const buf = typeof data === 'string' ? Buffer.from(data, 'utf-8') : data;
51
+ return encodeFrame(FrameType.DATA, buf);
52
+ }
53
+ /** Encode a RESIZE frame. */
54
+ export function encodeResize(msg) {
55
+ return encodeFrame(FrameType.RESIZE, Buffer.from(JSON.stringify(msg)));
56
+ }
57
+ /** Encode a SIGNAL frame. */
58
+ export function encodeSignal(msg) {
59
+ return encodeFrame(FrameType.SIGNAL, Buffer.from(JSON.stringify(msg)));
60
+ }
61
+ /** Encode an EXIT frame. */
62
+ export function encodeExit(msg) {
63
+ return encodeFrame(FrameType.EXIT, Buffer.from(JSON.stringify(msg)));
64
+ }
65
+ /** Encode a REPLAY frame (raw bytes). */
66
+ export function encodeReplay(data) {
67
+ return encodeFrame(FrameType.REPLAY, data);
68
+ }
69
+ /** Encode a PING frame. */
70
+ export function encodePing() {
71
+ return encodeFrame(FrameType.PING, Buffer.alloc(0));
72
+ }
73
+ /** Encode a PONG frame. */
74
+ export function encodePong() {
75
+ return encodeFrame(FrameType.PONG, Buffer.alloc(0));
76
+ }
77
+ /** Encode a HELLO frame. */
78
+ export function encodeHello(msg) {
79
+ return encodeFrame(FrameType.HELLO, Buffer.from(JSON.stringify(msg)));
80
+ }
81
+ /** Encode a WELCOME frame. */
82
+ export function encodeWelcome(msg) {
83
+ return encodeFrame(FrameType.WELCOME, Buffer.from(JSON.stringify(msg)));
84
+ }
85
+ /** Encode a SPAWN frame. */
86
+ export function encodeSpawn(msg) {
87
+ return encodeFrame(FrameType.SPAWN, Buffer.from(JSON.stringify(msg)));
88
+ }
89
+ // --- Streaming Frame Parser ---
90
+ /**
91
+ * A Transform stream that parses the binary frame protocol.
92
+ *
93
+ * Input: raw socket data (may be fragmented across chunks)
94
+ * Output: ParsedFrame objects (in objectMode)
95
+ *
96
+ * Emits 'frame-error' event on protocol violations (oversized frames,
97
+ * malformed headers). The stream is destroyed on error.
98
+ */
99
+ export class FrameParser extends Transform {
100
+ chunks = [];
101
+ bufferedLength = 0;
102
+ constructor() {
103
+ super({ readableObjectMode: true });
104
+ }
105
+ _transform(chunk, _encoding, callback) {
106
+ this.chunks.push(chunk);
107
+ this.bufferedLength += chunk.length;
108
+ try {
109
+ this.drainFrames();
110
+ callback();
111
+ }
112
+ catch (err) {
113
+ callback(err);
114
+ }
115
+ }
116
+ _flush(callback) {
117
+ if (this.bufferedLength > 0) {
118
+ callback(new Error(`Incomplete frame: ${this.bufferedLength} bytes remaining at end of stream`));
119
+ }
120
+ else {
121
+ callback();
122
+ }
123
+ }
124
+ drainFrames() {
125
+ while (this.bufferedLength >= HEADER_SIZE) {
126
+ // Peek at the header without consuming
127
+ const header = this.peek(HEADER_SIZE);
128
+ const payloadLength = header.readUInt32BE(1);
129
+ if (payloadLength > MAX_FRAME_SIZE) {
130
+ throw new Error(`Frame payload size ${payloadLength} exceeds maximum ${MAX_FRAME_SIZE}`);
131
+ }
132
+ const totalLength = HEADER_SIZE + payloadLength;
133
+ if (this.bufferedLength < totalLength) {
134
+ // Need more data
135
+ break;
136
+ }
137
+ // Consume the full frame
138
+ const frameData = this.consume(totalLength);
139
+ const type = frameData[0];
140
+ const payload = frameData.subarray(HEADER_SIZE);
141
+ this.push({ type, payload });
142
+ }
143
+ }
144
+ peek(n) {
145
+ if (this.chunks.length === 1 && this.chunks[0].length >= n) {
146
+ return this.chunks[0].subarray(0, n);
147
+ }
148
+ // Slow path: concat needed bytes
149
+ const parts = [];
150
+ let remaining = n;
151
+ for (const chunk of this.chunks) {
152
+ if (remaining <= 0)
153
+ break;
154
+ const take = Math.min(chunk.length, remaining);
155
+ parts.push(chunk.subarray(0, take));
156
+ remaining -= take;
157
+ }
158
+ return Buffer.concat(parts);
159
+ }
160
+ consume(n) {
161
+ if (this.chunks.length === 1 && this.chunks[0].length === n) {
162
+ const buf = this.chunks[0];
163
+ this.chunks = [];
164
+ this.bufferedLength = 0;
165
+ return buf;
166
+ }
167
+ if (this.chunks.length === 1 && this.chunks[0].length > n) {
168
+ const buf = this.chunks[0].subarray(0, n);
169
+ this.chunks[0] = this.chunks[0].subarray(n);
170
+ this.bufferedLength -= n;
171
+ return Buffer.from(buf); // Copy so subarray doesn't pin original
172
+ }
173
+ // Slow path: gather from multiple chunks
174
+ const result = Buffer.allocUnsafe(n);
175
+ let offset = 0;
176
+ let remaining = n;
177
+ while (remaining > 0) {
178
+ const chunk = this.chunks[0];
179
+ const take = Math.min(chunk.length, remaining);
180
+ chunk.copy(result, offset, 0, take);
181
+ offset += take;
182
+ remaining -= take;
183
+ if (take === chunk.length) {
184
+ this.chunks.shift();
185
+ }
186
+ else {
187
+ this.chunks[0] = chunk.subarray(take);
188
+ }
189
+ }
190
+ this.bufferedLength -= n;
191
+ return result;
192
+ }
193
+ }
194
+ /**
195
+ * Create a streaming frame parser.
196
+ * Convenience factory matching the plan's API.
197
+ */
198
+ export function createFrameParser() {
199
+ return new FrameParser();
200
+ }
201
+ // --- JSON Payload Helpers ---
202
+ const KNOWN_FRAME_TYPES = new Set(Object.values(FrameType));
203
+ /** Check if a frame type is a known type. */
204
+ export function isKnownFrameType(type) {
205
+ return KNOWN_FRAME_TYPES.has(type);
206
+ }
207
+ /**
208
+ * Parse a JSON payload from a control frame.
209
+ * Throws on invalid JSON.
210
+ */
211
+ export function parseJsonPayload(payload) {
212
+ return JSON.parse(payload.toString('utf-8'));
213
+ }
214
+ //# sourceMappingURL=shepherd-protocol.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shepherd-protocol.js","sourceRoot":"","sources":["../../src/terminal/shepherd-protocol.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Standalone replay buffer for the shepherd process.
3
+ *
4
+ * Unlike RingBuffer (which stores lines), this stores raw byte chunks
5
+ * to preserve exact terminal output including escape sequences. It tracks
6
+ * the total bytes stored and evicts oldest chunks when the limit is exceeded.
7
+ *
8
+ * This module has NO dependencies beyond Node.js built-ins so the shepherd
9
+ * process doesn't need to pull in the full package dependency tree.
10
+ */
11
+ export declare class ShepherdReplayBuffer {
12
+ private chunks;
13
+ private totalBytes;
14
+ private readonly maxLines;
15
+ private lineCount;
16
+ /**
17
+ * @param maxLines Maximum number of lines to retain. Lines are delimited
18
+ * by newline characters in the raw data stream.
19
+ */
20
+ constructor(maxLines?: number);
21
+ /**
22
+ * Append raw PTY output data to the buffer.
23
+ * Evicts oldest chunks if the line count exceeds maxLines.
24
+ */
25
+ append(data: Buffer | string): void;
26
+ /**
27
+ * Get all buffered data as a single concatenated Buffer.
28
+ * Used for the REPLAY frame on reconnection.
29
+ */
30
+ getReplayData(): Buffer;
31
+ /** Current number of bytes stored. */
32
+ get size(): number;
33
+ /** Approximate number of lines stored. */
34
+ get lines(): number;
35
+ /** Clear all buffered data. */
36
+ clear(): void;
37
+ }
38
+ //# sourceMappingURL=shepherd-replay-buffer.d.ts.map