@minhworker/agent-room 0.1.0

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/server.js ADDED
@@ -0,0 +1,239 @@
1
+ import { createServer } from 'node:http';
2
+ import { AgentRoomDatabase } from './database.js';
3
+ import { AppError, errorMessage } from './errors.js';
4
+ import { EventHub } from './event-hub.js';
5
+ function sendJson(response, status, data) {
6
+ const body = JSON.stringify(data);
7
+ response.writeHead(status, {
8
+ 'content-type': 'application/json; charset=utf-8',
9
+ 'content-length': Buffer.byteLength(body),
10
+ });
11
+ response.end(body);
12
+ }
13
+ async function readJson(request) {
14
+ const chunks = [];
15
+ let size = 0;
16
+ for await (const chunk of request) {
17
+ const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
18
+ size += buffer.length;
19
+ if (size > 1_000_000) {
20
+ throw new AppError('Request body exceeds 1 MB.', 413, 'body_too_large');
21
+ }
22
+ chunks.push(buffer);
23
+ }
24
+ try {
25
+ const parsed = JSON.parse(Buffer.concat(chunks).toString('utf8'));
26
+ if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed)) {
27
+ throw new Error('Expected a JSON object.');
28
+ }
29
+ return parsed;
30
+ }
31
+ catch {
32
+ throw new AppError('Request body must be a valid JSON object.', 400, 'invalid_json');
33
+ }
34
+ }
35
+ function requireString(body, key) {
36
+ const value = body[key];
37
+ if (typeof value !== 'string') {
38
+ throw new AppError(`Field "${key}" must be a string.`, 400, 'invalid_request');
39
+ }
40
+ return value;
41
+ }
42
+ function optionalString(body, key) {
43
+ const value = body[key];
44
+ if (value === undefined || value === null) {
45
+ return null;
46
+ }
47
+ if (typeof value !== 'string') {
48
+ throw new AppError(`Field "${key}" must be a string or null.`, 400, 'invalid_request');
49
+ }
50
+ return value;
51
+ }
52
+ function parseInteger(value, fallback, key) {
53
+ if (value === null) {
54
+ return fallback;
55
+ }
56
+ const number = Number(value);
57
+ if (!Number.isSafeInteger(number) || number < 0) {
58
+ throw new AppError(`Query parameter "${key}" must be a non-negative integer.`, 400, 'invalid_query');
59
+ }
60
+ return number;
61
+ }
62
+ function pathSegments(url) {
63
+ return url.pathname
64
+ .split('/')
65
+ .filter((segment) => segment.length > 0)
66
+ .map((segment) => decodeURIComponent(segment));
67
+ }
68
+ export function createAgentRoomServer(options) {
69
+ const host = options.host ?? '127.0.0.1';
70
+ const port = options.port ?? 7337;
71
+ const database = new AgentRoomDatabase(options.dbPath);
72
+ const events = new EventHub();
73
+ const streams = new Set();
74
+ let started = false;
75
+ let stopped = false;
76
+ const server = createServer((request, response) => {
77
+ void handleRequest(request, response).catch((error) => {
78
+ if (response.headersSent) {
79
+ response.end();
80
+ return;
81
+ }
82
+ const status = error instanceof AppError ? error.status : 500;
83
+ const code = error instanceof AppError ? error.code : 'internal_error';
84
+ sendJson(response, status, { error: { code, message: errorMessage(error) } });
85
+ });
86
+ });
87
+ async function handleRequest(request, response) {
88
+ const method = request.method ?? 'GET';
89
+ const url = new URL(request.url ?? '/', `http://${request.headers.host ?? 'localhost'}`);
90
+ const segments = pathSegments(url);
91
+ if (method === 'GET' && segments.length === 1 && segments[0] === 'health') {
92
+ sendJson(response, 200, { ok: true });
93
+ return;
94
+ }
95
+ if (method === 'GET' && segments.length === 1 && segments[0] === 'rooms') {
96
+ sendJson(response, 200, { rooms: database.listRooms() });
97
+ return;
98
+ }
99
+ if (method === 'POST' && segments.length === 1 && segments[0] === 'rooms') {
100
+ const body = await readJson(request);
101
+ const result = database.createRoom(requireString(body, 'name'));
102
+ if (result.event !== null) {
103
+ events.publish(result.event);
104
+ }
105
+ sendJson(response, 201, { room: result.value });
106
+ return;
107
+ }
108
+ if (segments.length >= 2 && segments[0] === 'rooms') {
109
+ const room = segments[1];
110
+ if (room === undefined) {
111
+ throw new AppError('Room name is required.', 400, 'invalid_room_name');
112
+ }
113
+ if (method === 'GET' && segments.length === 3 && segments[2] === 'cursor') {
114
+ sendJson(response, 200, { cursor: database.latestCursor(room) });
115
+ return;
116
+ }
117
+ if (method === 'POST' && segments.length === 3 && segments[2] === 'join') {
118
+ const body = await readJson(request);
119
+ const result = database.join(room, requireString(body, 'name'));
120
+ if (result.event !== null) {
121
+ events.publish(result.event);
122
+ }
123
+ sendJson(response, result.value.changed ? 201 : 200, result.value);
124
+ return;
125
+ }
126
+ if (method === 'POST' && segments.length === 3 && segments[2] === 'leave') {
127
+ const body = await readJson(request);
128
+ const result = database.leave(room, requireString(body, 'name'));
129
+ if (result.event !== null) {
130
+ events.publish(result.event);
131
+ }
132
+ sendJson(response, 200, { participant: result.value });
133
+ return;
134
+ }
135
+ if (method === 'POST' && segments.length === 3 && segments[2] === 'messages') {
136
+ const body = await readJson(request);
137
+ const result = database.send(room, requireString(body, 'from'), requireString(body, 'body'), optionalString(body, 'replyTo'));
138
+ if (result.event !== null) {
139
+ events.publish(result.event);
140
+ }
141
+ sendJson(response, 201, { message: result.value });
142
+ return;
143
+ }
144
+ if (method === 'GET' && segments.length === 3 && segments[2] === 'messages') {
145
+ const limit = parseInteger(url.searchParams.get('limit'), 50, 'limit');
146
+ const rawAfter = url.searchParams.get('after');
147
+ const after = rawAfter === null ? undefined : parseInteger(rawAfter, 0, 'after');
148
+ sendJson(response, 200, { messages: database.history(room, limit, after) });
149
+ return;
150
+ }
151
+ if (method === 'GET' && segments.length === 3 && segments[2] === 'events') {
152
+ const participant = url.searchParams.get('name');
153
+ if (participant === null) {
154
+ throw new AppError('Query parameter "name" is required.', 400, 'invalid_query');
155
+ }
156
+ const after = parseInteger(url.searchParams.get('after'), 0, 'after');
157
+ const foundRoom = database.assertCanWatch(room, participant);
158
+ const replay = database.listEvents(foundRoom.id, after);
159
+ streamEvents(request, response, foundRoom.id, after, replay);
160
+ return;
161
+ }
162
+ }
163
+ throw new AppError('Route not found.', 404, 'not_found');
164
+ }
165
+ function streamEvents(request, response, roomId, after, replay) {
166
+ let cursor = after;
167
+ let closed = false;
168
+ streams.add(response);
169
+ response.writeHead(200, {
170
+ 'content-type': 'application/x-ndjson; charset=utf-8',
171
+ 'cache-control': 'no-cache, no-transform',
172
+ connection: 'keep-alive',
173
+ 'x-accel-buffering': 'no',
174
+ });
175
+ response.flushHeaders();
176
+ const write = (event) => {
177
+ if (!closed && event.cursor > cursor) {
178
+ cursor = event.cursor;
179
+ response.write(`${JSON.stringify(event)}\n`);
180
+ }
181
+ };
182
+ const unsubscribe = events.subscribe(roomId, write);
183
+ for (const event of replay) {
184
+ write(event);
185
+ }
186
+ const heartbeat = setInterval(() => {
187
+ if (!closed) {
188
+ response.write('\n');
189
+ }
190
+ }, 15_000);
191
+ const cleanup = () => {
192
+ if (closed) {
193
+ return;
194
+ }
195
+ closed = true;
196
+ clearInterval(heartbeat);
197
+ unsubscribe();
198
+ streams.delete(response);
199
+ };
200
+ request.once('close', cleanup);
201
+ response.once('close', cleanup);
202
+ }
203
+ return {
204
+ async start() {
205
+ if (started) {
206
+ throw new AppError('Server has already been started.', 500, 'server_state');
207
+ }
208
+ started = true;
209
+ await new Promise((resolve, reject) => {
210
+ const onError = (error) => reject(error);
211
+ server.once('error', onError);
212
+ server.listen(port, host, () => {
213
+ server.off('error', onError);
214
+ resolve();
215
+ });
216
+ });
217
+ const address = server.address();
218
+ return { host, port: address.port, url: `http://${host}:${address.port}` };
219
+ },
220
+ async stop() {
221
+ if (stopped) {
222
+ return;
223
+ }
224
+ stopped = true;
225
+ for (const stream of streams) {
226
+ stream.end();
227
+ }
228
+ streams.clear();
229
+ if (started) {
230
+ await new Promise((resolve, reject) => {
231
+ server.close((error) => (error === undefined ? resolve() : reject(error)));
232
+ server.closeAllConnections();
233
+ });
234
+ }
235
+ database.close();
236
+ },
237
+ };
238
+ }
239
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "@minhworker/agent-room",
3
+ "version": "0.1.0",
4
+ "description": "Local terminal rooms for coding agents and humans",
5
+ "type": "module",
6
+ "bin": {
7
+ "agent-room": "dist/cli.js"
8
+ },
9
+ "files": [
10
+ "dist",
11
+ "README.md",
12
+ "LICENSE"
13
+ ],
14
+ "scripts": {
15
+ "build": "tsc -p tsconfig.build.json",
16
+ "test": "vitest run",
17
+ "test:watch": "vitest",
18
+ "typecheck": "tsc --noEmit -p tsconfig.json"
19
+ },
20
+ "engines": {
21
+ "node": ">=22.12.0"
22
+ },
23
+ "repository": {
24
+ "type": "git",
25
+ "url": "git+https://github.com/MinhWorker/agent-room.git",
26
+ "directory": "packages/cli"
27
+ },
28
+ "bugs": {
29
+ "url": "https://github.com/MinhWorker/agent-room/issues"
30
+ },
31
+ "homepage": "https://github.com/MinhWorker/agent-room#readme",
32
+ "license": "MIT",
33
+ "publishConfig": {
34
+ "access": "public"
35
+ },
36
+ "dependencies": {
37
+ "better-sqlite3": "^12.11.1",
38
+ "commander": "^15.0.0"
39
+ },
40
+ "devDependencies": {
41
+ "@types/better-sqlite3": "^7.6.13",
42
+ "@types/node": "^26.1.1",
43
+ "tsx": "^4.20.6",
44
+ "typescript": "^7.0.2",
45
+ "vitest": "^4.1.10"
46
+ }
47
+ }