browser-devtools-mcp 0.1.7 → 0.2.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.
Files changed (163) hide show
  1. package/LICENSE +93 -21
  2. package/README.md +93 -16
  3. package/dist/cli.js +53 -1721
  4. package/dist/core.js +764 -0
  5. package/dist/daemon-server.js +1 -338
  6. package/dist/index.d.ts +2 -0
  7. package/dist/index.js +210 -80
  8. package/dist/otel/otel-initializer.bundle.js +0 -1
  9. package/dist/tools/a11y/index.d.ts +2 -0
  10. package/dist/tools/content/index.d.ts +2 -0
  11. package/dist/tools/debug/index.d.ts +2 -0
  12. package/dist/tools/figma/compare/index.d.ts +56 -0
  13. package/dist/tools/figma/compare/types.d.ts +15 -0
  14. package/dist/tools/figma/index.d.ts +2 -0
  15. package/dist/tools/index.d.ts +4 -0
  16. package/dist/tools/interaction/index.d.ts +2 -0
  17. package/dist/tools/navigation/index.d.ts +2 -0
  18. package/dist/tools/o11y/index.d.ts +2 -0
  19. package/dist/tools/react/index.d.ts +2 -0
  20. package/dist/tools/run/index.d.ts +2 -0
  21. package/dist/tools/stub/index.d.ts +2 -0
  22. package/dist/tools/sync/index.d.ts +2 -0
  23. package/dist/tools/types.d.ts +21 -0
  24. package/dist/types.d.ts +78 -0
  25. package/package.json +11 -11
  26. package/dist/browser.js +0 -213
  27. package/dist/browser.js.map +0 -1
  28. package/dist/cli.js.map +0 -1
  29. package/dist/config.js +0 -96
  30. package/dist/config.js.map +0 -1
  31. package/dist/context.js +0 -298
  32. package/dist/context.js.map +0 -1
  33. package/dist/daemon-server.js.map +0 -1
  34. package/dist/index.js.map +0 -1
  35. package/dist/logger.js +0 -97
  36. package/dist/logger.js.map +0 -1
  37. package/dist/mcp-server.js +0 -401
  38. package/dist/mcp-server.js.map +0 -1
  39. package/dist/otel/otel-controller.js +0 -323
  40. package/dist/otel/otel-controller.js.map +0 -1
  41. package/dist/otel/otel-initializer.bundle.js.map +0 -7
  42. package/dist/otel/otel-proxy.js +0 -407
  43. package/dist/otel/otel-proxy.js.map +0 -1
  44. package/dist/server-info.js +0 -186
  45. package/dist/server-info.js.map +0 -1
  46. package/dist/tools/a11y/index.js +0 -7
  47. package/dist/tools/a11y/index.js.map +0 -1
  48. package/dist/tools/a11y/take-aria-snapshot.js +0 -54
  49. package/dist/tools/a11y/take-aria-snapshot.js.map +0 -1
  50. package/dist/tools/a11y/take-ax-tree-snapshot.js +0 -850
  51. package/dist/tools/a11y/take-ax-tree-snapshot.js.map +0 -1
  52. package/dist/tools/content/get-as-html.js +0 -164
  53. package/dist/tools/content/get-as-html.js.map +0 -1
  54. package/dist/tools/content/get-as-text.js +0 -76
  55. package/dist/tools/content/get-as-text.js.map +0 -1
  56. package/dist/tools/content/index.js +0 -14
  57. package/dist/tools/content/index.js.map +0 -1
  58. package/dist/tools/content/save-as-pdf.js +0 -119
  59. package/dist/tools/content/save-as-pdf.js.map +0 -1
  60. package/dist/tools/content/take-screenshot.js +0 -297
  61. package/dist/tools/content/take-screenshot.js.map +0 -1
  62. package/dist/tools/figma/compare/compare-image-embedding.js +0 -159
  63. package/dist/tools/figma/compare/compare-image-embedding.js.map +0 -1
  64. package/dist/tools/figma/compare/compare-mssim.js +0 -98
  65. package/dist/tools/figma/compare/compare-mssim.js.map +0 -1
  66. package/dist/tools/figma/compare/compare-text-embedding.js +0 -291
  67. package/dist/tools/figma/compare/compare-text-embedding.js.map +0 -1
  68. package/dist/tools/figma/compare/index.js +0 -139
  69. package/dist/tools/figma/compare/index.js.map +0 -1
  70. package/dist/tools/figma/compare/types.js +0 -3
  71. package/dist/tools/figma/compare/types.js.map +0 -1
  72. package/dist/tools/figma/compare/vector.js +0 -46
  73. package/dist/tools/figma/compare/vector.js.map +0 -1
  74. package/dist/tools/figma/compare-page-with-design.js +0 -240
  75. package/dist/tools/figma/compare-page-with-design.js.map +0 -1
  76. package/dist/tools/figma/figma-service.js +0 -134
  77. package/dist/tools/figma/figma-service.js.map +0 -1
  78. package/dist/tools/figma/index.js +0 -6
  79. package/dist/tools/figma/index.js.map +0 -1
  80. package/dist/tools/index.js +0 -41
  81. package/dist/tools/index.js.map +0 -1
  82. package/dist/tools/interaction/click.js +0 -29
  83. package/dist/tools/interaction/click.js.map +0 -1
  84. package/dist/tools/interaction/drag.js +0 -41
  85. package/dist/tools/interaction/drag.js.map +0 -1
  86. package/dist/tools/interaction/fill.js +0 -28
  87. package/dist/tools/interaction/fill.js.map +0 -1
  88. package/dist/tools/interaction/hover.js +0 -29
  89. package/dist/tools/interaction/hover.js.map +0 -1
  90. package/dist/tools/interaction/index.js +0 -24
  91. package/dist/tools/interaction/index.js.map +0 -1
  92. package/dist/tools/interaction/press-key.js +0 -99
  93. package/dist/tools/interaction/press-key.js.map +0 -1
  94. package/dist/tools/interaction/resize-viewport.js +0 -110
  95. package/dist/tools/interaction/resize-viewport.js.map +0 -1
  96. package/dist/tools/interaction/resize-window.js +0 -261
  97. package/dist/tools/interaction/resize-window.js.map +0 -1
  98. package/dist/tools/interaction/scroll.js +0 -304
  99. package/dist/tools/interaction/scroll.js.map +0 -1
  100. package/dist/tools/interaction/select.js +0 -30
  101. package/dist/tools/interaction/select.js.map +0 -1
  102. package/dist/tools/navigation/go-back.js +0 -76
  103. package/dist/tools/navigation/go-back.js.map +0 -1
  104. package/dist/tools/navigation/go-forward.js +0 -76
  105. package/dist/tools/navigation/go-forward.js.map +0 -1
  106. package/dist/tools/navigation/go-to.js +0 -80
  107. package/dist/tools/navigation/go-to.js.map +0 -1
  108. package/dist/tools/navigation/index.js +0 -14
  109. package/dist/tools/navigation/index.js.map +0 -1
  110. package/dist/tools/navigation/reload.js +0 -76
  111. package/dist/tools/navigation/reload.js.map +0 -1
  112. package/dist/tools/o11y/get-console-messages.js +0 -151
  113. package/dist/tools/o11y/get-console-messages.js.map +0 -1
  114. package/dist/tools/o11y/get-http-requests.js +0 -216
  115. package/dist/tools/o11y/get-http-requests.js.map +0 -1
  116. package/dist/tools/o11y/get-trace-id.js +0 -30
  117. package/dist/tools/o11y/get-trace-id.js.map +0 -1
  118. package/dist/tools/o11y/get-web-vitals.js +0 -595
  119. package/dist/tools/o11y/get-web-vitals.js.map +0 -1
  120. package/dist/tools/o11y/index.js +0 -18
  121. package/dist/tools/o11y/index.js.map +0 -1
  122. package/dist/tools/o11y/new-trace-id.js +0 -32
  123. package/dist/tools/o11y/new-trace-id.js.map +0 -1
  124. package/dist/tools/o11y/set-trace-id.js +0 -28
  125. package/dist/tools/o11y/set-trace-id.js.map +0 -1
  126. package/dist/tools/react/get-component-for-element.js +0 -941
  127. package/dist/tools/react/get-component-for-element.js.map +0 -1
  128. package/dist/tools/react/get-element-for-component.js +0 -1190
  129. package/dist/tools/react/get-element-for-component.js.map +0 -1
  130. package/dist/tools/react/index.js +0 -10
  131. package/dist/tools/react/index.js.map +0 -1
  132. package/dist/tools/run/index.js +0 -7
  133. package/dist/tools/run/index.js.map +0 -1
  134. package/dist/tools/run/js-in-browser.js +0 -51
  135. package/dist/tools/run/js-in-browser.js.map +0 -1
  136. package/dist/tools/run/js-in-sandbox.js +0 -175
  137. package/dist/tools/run/js-in-sandbox.js.map +0 -1
  138. package/dist/tools/stub/clear.js +0 -41
  139. package/dist/tools/stub/clear.js.map +0 -1
  140. package/dist/tools/stub/index.js +0 -14
  141. package/dist/tools/stub/index.js.map +0 -1
  142. package/dist/tools/stub/intercept-http-request.js +0 -112
  143. package/dist/tools/stub/intercept-http-request.js.map +0 -1
  144. package/dist/tools/stub/list.js +0 -75
  145. package/dist/tools/stub/list.js.map +0 -1
  146. package/dist/tools/stub/mock-http-response.js +0 -152
  147. package/dist/tools/stub/mock-http-response.js.map +0 -1
  148. package/dist/tools/stub/stub-controller.js +0 -284
  149. package/dist/tools/stub/stub-controller.js.map +0 -1
  150. package/dist/tools/sync/index.js +0 -6
  151. package/dist/tools/sync/index.js.map +0 -1
  152. package/dist/tools/sync/wait-for-network-idle.js +0 -152
  153. package/dist/tools/sync/wait-for-network-idle.js.map +0 -1
  154. package/dist/tools/tool-executor.js +0 -79
  155. package/dist/tools/tool-executor.js.map +0 -1
  156. package/dist/tools/types.js +0 -3
  157. package/dist/tools/types.js.map +0 -1
  158. package/dist/types.js +0 -55
  159. package/dist/types.js.map +0 -1
  160. package/dist/utils/cli-utils.js +0 -253
  161. package/dist/utils/cli-utils.js.map +0 -1
  162. package/dist/utils.js +0 -85
  163. package/dist/utils.js.map +0 -1
@@ -1,338 +1 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
- Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.startDaemonHTTPServer = startDaemonHTTPServer;
37
- const config = __importStar(require("./config"));
38
- const logger = __importStar(require("./logger"));
39
- const tools_1 = require("./tools");
40
- const node_server_1 = require("@hono/node-server");
41
- const hono_1 = require("hono");
42
- const cors_1 = require("hono/cors");
43
- const zod_1 = require("zod");
44
- let daemonStartTime = 0;
45
- let daemonPort = 0;
46
- const app = new hono_1.Hono();
47
- const sessions = new Map();
48
- const DEFAULT_SESSION_ID = '#default';
49
- const ERRORS = {
50
- get sessionNotFound() {
51
- return _buildErrorResponse(404, 'Session Not Found');
52
- },
53
- get toolNotFound() {
54
- return _buildErrorResponse(404, 'Tool Not Found');
55
- },
56
- get internalServerError() {
57
- return _buildErrorResponse(500, 'Internal Server Error');
58
- },
59
- };
60
- function _buildErrorResponse(code, message) {
61
- return {
62
- error: {
63
- code: code,
64
- message: message,
65
- },
66
- };
67
- }
68
- async function _closeSession(session) {
69
- session.closed = true;
70
- if (session.context) {
71
- try {
72
- await session.context.close();
73
- logger.debug('Closed MCP session context');
74
- }
75
- catch (err) {
76
- logger.error('Error occurred while closing MCP session context', err);
77
- }
78
- }
79
- sessions.delete(session.id);
80
- }
81
- function _createSession(ctx, sessionId) {
82
- const now = Date.now();
83
- const session = {
84
- id: sessionId,
85
- toolExecutor: new tools_1.ToolExecutor(() => sessionId),
86
- closed: false,
87
- createdAt: now,
88
- lastActiveAt: now,
89
- };
90
- logger.debug(`Created session with id ${sessionId}`);
91
- return session;
92
- }
93
- function _getSessionInfo(session) {
94
- const now = Date.now();
95
- return {
96
- id: session.id,
97
- createdAt: session.createdAt,
98
- lastActiveAt: session.lastActiveAt,
99
- idleSeconds: Math.floor((now - session.lastActiveAt) / 1000),
100
- };
101
- }
102
- async function _getSession(ctx) {
103
- const sessionId = ctx.req.header('session-id') || DEFAULT_SESSION_ID;
104
- return sessions.get(sessionId);
105
- }
106
- async function _getOrCreateSession(ctx) {
107
- const sessionId = ctx.req.header('session-id') || DEFAULT_SESSION_ID;
108
- let session = sessions.get(sessionId);
109
- if (session) {
110
- logger.debug(`Reusing session with id ${sessionId}`);
111
- }
112
- else {
113
- logger.debug(`No session could be found with id ${sessionId}`);
114
- session = _createSession(ctx, sessionId);
115
- sessions.set(sessionId, session);
116
- }
117
- return session;
118
- }
119
- function _scheduleIdleSessionCheck() {
120
- let noActiveSession = false;
121
- const sessionCheck = () => {
122
- const currentTime = Date.now();
123
- if (noActiveSession && sessions.size === 0) {
124
- // There is no active session from last check and still there is no active session
125
- logger.info('No active session found, so terminating daemon server');
126
- process.exit(0);
127
- }
128
- for (const [sessionId, session] of sessions) {
129
- logger.debug(`Checking whether session with id ${sessionId} is idle or not ...`);
130
- if (currentTime - session.lastActiveAt >
131
- config.DAEMON_SESSION_IDLE_SECONDS * 1000) {
132
- logger.debug(`Session with id ${sessionId} is idle, so it will be closing ...`);
133
- _closeSession(session)
134
- .then(() => {
135
- logger.debug(`Session with id ${sessionId} was idle, so it has been closed`);
136
- })
137
- .catch((err) => {
138
- logger.error(`Unable to delete idle session with id ${sessionId}`, err);
139
- });
140
- }
141
- }
142
- noActiveSession = sessions.size === 0;
143
- };
144
- setInterval(sessionCheck, config.DAEMON_SESSION_IDLE_CHECK_SECONDS * 1000);
145
- }
146
- async function _logRequest(ctx) {
147
- const reqClone = ctx.req.raw.clone();
148
- logger.debug(`Got request: ${await reqClone.json()}`);
149
- }
150
- async function startDaemonHTTPServer(port) {
151
- const toolMap = Object.fromEntries(tools_1.tools.map((tool) => [tool.name(), tool]));
152
- // Global CORS
153
- app.use('*', (0, cors_1.cors)({
154
- origin: '*',
155
- allowMethods: ['GET', 'POST', 'DELETE', 'OPTIONS'],
156
- allowHeaders: ['Content-Type', 'Authorization', 'session-id'],
157
- }));
158
- // Store daemon port and start time
159
- daemonPort = port;
160
- daemonStartTime = Date.now();
161
- // Graceful shutdown handler
162
- const gracefulShutdown = async (signal) => {
163
- logger.info(`Received ${signal}, initiating graceful shutdown...`);
164
- // Close all sessions
165
- const closePromises = [];
166
- for (const session of sessions.values()) {
167
- closePromises.push(_closeSession(session));
168
- }
169
- await Promise.allSettled(closePromises);
170
- logger.info('All sessions closed, exiting...');
171
- process.exit(0);
172
- };
173
- process.on('SIGTERM', () => gracefulShutdown('SIGTERM'));
174
- process.on('SIGINT', () => gracefulShutdown('SIGINT'));
175
- // Handle uncaught errors to prevent crashes
176
- process.on('uncaughtException', (err) => {
177
- logger.error('Uncaught exception', err);
178
- });
179
- process.on('unhandledRejection', (reason) => {
180
- logger.error('Unhandled rejection', reason);
181
- });
182
- // MCP Health
183
- app.get('/health', (ctx) => ctx.json({ status: 'ok' }));
184
- // Daemon info
185
- app.get('/info', (ctx) => {
186
- const info = {
187
- version: require('../package.json').version,
188
- uptime: Math.floor((Date.now() - daemonStartTime) / 1000),
189
- sessionCount: sessions.size,
190
- port: daemonPort,
191
- };
192
- return ctx.json(info);
193
- });
194
- // List all sessions
195
- app.get('/sessions', (ctx) => {
196
- const sessionList = [];
197
- for (const session of sessions.values()) {
198
- sessionList.push(_getSessionInfo(session));
199
- }
200
- return ctx.json({ sessions: sessionList });
201
- });
202
- // Get session info
203
- app.get('/session', async (ctx) => {
204
- const session = await _getSession(ctx);
205
- if (!session) {
206
- return ctx.json(ERRORS.sessionNotFound, 404);
207
- }
208
- return ctx.json(_getSessionInfo(session));
209
- });
210
- // Shutdown daemon server
211
- app.post('/shutdown', async (ctx) => {
212
- logger.info('Shutdown request received, closing all sessions...');
213
- // Close all sessions
214
- const closePromises = [];
215
- for (const session of sessions.values()) {
216
- closePromises.push(_closeSession(session));
217
- }
218
- await Promise.allSettled(closePromises);
219
- logger.info('All sessions closed, shutting down daemon server...');
220
- // Schedule process exit after response is sent
221
- setTimeout(() => {
222
- process.exit(0);
223
- }, 500);
224
- return ctx.json({ status: 'shutting_down' }, 200);
225
- });
226
- // Call message
227
- app.post('/call', async (ctx) => {
228
- try {
229
- if (logger.isDebugEnabled()) {
230
- await _logRequest(ctx);
231
- }
232
- const session = await _getOrCreateSession(ctx);
233
- session.lastActiveAt = Date.now();
234
- const toolCallRequest = (await ctx.req.json());
235
- const tool = toolMap[toolCallRequest.toolName];
236
- if (!tool) {
237
- return ctx.json(ERRORS.toolNotFound, 404);
238
- }
239
- let toolInput;
240
- try {
241
- const schema = zod_1.z.object(tool.inputSchema());
242
- toolInput = schema.parse(toolCallRequest.toolInput);
243
- }
244
- catch (err) {
245
- // Return validation error with details
246
- const errorMessage = err.errors && Array.isArray(err.errors)
247
- ? err.errors
248
- .map((e) => `${e.path?.join('.') || 'input'}: ${e.message}`)
249
- .join('; ')
250
- : 'Invalid tool input';
251
- return ctx.json(_buildErrorResponse(400, `Invalid Tool Request: ${errorMessage}`), 400);
252
- }
253
- try {
254
- const toolOutput = await session.toolExecutor.executeTool(tool, toolInput);
255
- const toolCallResponse = {
256
- toolOutput,
257
- };
258
- return ctx.json(toolCallResponse, 200);
259
- }
260
- catch (err) {
261
- const toolCallResponse = {
262
- toolError: {
263
- code: err.code,
264
- message: err.message,
265
- },
266
- };
267
- return ctx.json(toolCallResponse, 500);
268
- }
269
- }
270
- catch (err) {
271
- logger.error('Error occurred while handling tool call request', err);
272
- return ctx.json(ERRORS.internalServerError, 500);
273
- }
274
- });
275
- // Delete session
276
- app.delete('/session', async (ctx) => {
277
- try {
278
- const session = await _getSession(ctx);
279
- if (!session) {
280
- return ctx.json(ERRORS.sessionNotFound, 404);
281
- }
282
- await _closeSession(session);
283
- return ctx.json({ ok: true }, 200);
284
- }
285
- catch (err) {
286
- logger.error('Error occurred while deleting session', err);
287
- return ctx.json(ERRORS.internalServerError, 500);
288
- }
289
- });
290
- // Global error handler
291
- app.onError((err, ctx) => {
292
- logger.error('Unhandled error in request handler', err);
293
- return ctx.json({
294
- error: {
295
- code: 500,
296
- message: 'Internal Server Error',
297
- },
298
- }, 500);
299
- });
300
- // 404
301
- app.notFound((ctx) => ctx.json({ error: 'Not Found', status: 404 }, 404));
302
- // Listener for Node
303
- (0, node_server_1.serve)({
304
- fetch: app.fetch,
305
- port,
306
- }, () => logger.info(`Listening on port ${port}`));
307
- // Schedule background task to check (and remove) idle sessions
308
- _scheduleIdleSessionCheck();
309
- }
310
- // Main entry point when run directly
311
- if (require.main === module) {
312
- const { Command, InvalidOptionArgumentError, Option, } = require('commander');
313
- function parsePort(value) {
314
- const n = Number(value);
315
- if (!Number.isInteger(n) || n < 1 || n > 65535) {
316
- throw new InvalidOptionArgumentError('port must be an integer between 1 and 65535');
317
- }
318
- return n;
319
- }
320
- const program = new Command()
321
- .addOption(new Option('--port <number>', 'port for daemon HTTP server')
322
- .argParser(parsePort)
323
- .default(config.DAEMON_PORT))
324
- .allowUnknownOption()
325
- .parse(process.argv);
326
- const options = program.opts();
327
- logger.enable();
328
- logger.info('Starting daemon HTTP server...');
329
- startDaemonHTTPServer(options.port)
330
- .then(() => {
331
- logger.info('Daemon HTTP server started');
332
- })
333
- .catch((err) => {
334
- logger.error('Failed to start daemon HTTP server', err);
335
- process.exit(1);
336
- });
337
- }
338
- //# sourceMappingURL=daemon-server.js.map
1
+ import{A as C,C as y,D as u,E as c,F as d,G as I,H as D,a as t,x as T,y as b,z as E}from"./core.js";import{createRequire as N}from"module";import{Command as x,Option as _,InvalidOptionArgumentError as q}from"commander";import{serve as M}from"@hono/node-server";import{Hono as $}from"hono";import{cors as F}from"hono/cors";import{z as k}from"zod";var H=N(import.meta.url),A=0,R=0,i=new $,a=new Map,P="#default",p={get sessionNotFound(){return f(404,"Session Not Found")},get toolNotFound(){return f(404,"Tool Not Found")},get internalServerError(){return f(500,"Internal Server Error")}};function f(n,r){return{error:{code:n,message:r}}}t(f,"_buildErrorResponse");async function S(n){if(n.closed=!0,n.context)try{await n.context.close(),u("Closed MCP session context")}catch(r){d("Error occurred while closing MCP session context",r)}a.delete(n.id)}t(S,"_closeSession");function G(n,r){let s=Date.now(),e={id:r,toolExecutor:new I(()=>r),closed:!1,createdAt:s,lastActiveAt:s};return u(`Created session with id ${r}`),e}t(G,"_createSession");function j(n){let r=Date.now();return{id:n.id,createdAt:n.createdAt,lastActiveAt:n.lastActiveAt,idleSeconds:Math.floor((r-n.lastActiveAt)/1e3)}}t(j,"_getSessionInfo");async function O(n){let r=n.req.header("session-id")||P;return a.get(r)}t(O,"_getSession");async function L(n){let r=n.req.header("session-id")||P,s=a.get(r);return s?u(`Reusing session with id ${r}`):(u(`No session could be found with id ${r}`),s=G(n,r),a.set(r,s)),s}t(L,"_getOrCreateSession");function U(){let n=!1;setInterval(t(()=>{let s=Date.now();n&&a.size===0&&(c("No active session found, so terminating daemon server"),process.exit(0));for(let[e,o]of a)u(`Checking whether session with id ${e} is idle or not ...`),s-o.lastActiveAt>b*1e3&&(u(`Session with id ${e} is idle, so it will be closing ...`),S(o).then(()=>{u(`Session with id ${e} was idle, so it has been closed`)}).catch(l=>{d(`Unable to delete idle session with id ${e}`,l)}));n=a.size===0},"sessionCheck"),E*1e3)}t(U,"_scheduleIdleSessionCheck");async function z(n){let r=n.req.raw.clone();u(`Got request: ${await r.json()}`)}t(z,"_logRequest");async function W(n){let r=Object.fromEntries(D.map(e=>[e.name(),e]));i.use("*",F({origin:"*",allowMethods:["GET","POST","DELETE","OPTIONS"],allowHeaders:["Content-Type","Authorization","session-id"]})),R=n,A=Date.now();let s=t(async e=>{c(`Received ${e}, initiating graceful shutdown...`);let o=[];for(let l of a.values())o.push(S(l));await Promise.allSettled(o),c("All sessions closed, exiting..."),process.exit(0)},"gracefulShutdown");process.on("SIGTERM",()=>s("SIGTERM")),process.on("SIGINT",()=>s("SIGINT")),process.on("uncaughtException",e=>{d("Uncaught exception",e)}),process.on("unhandledRejection",e=>{d("Unhandled rejection",e)}),i.get("/health",e=>e.json({status:"ok"})),i.get("/info",e=>{let o={version:H("../package.json").version,uptime:Math.floor((Date.now()-A)/1e3),sessionCount:a.size,port:R};return e.json(o)}),i.get("/sessions",e=>{let o=[];for(let l of a.values())o.push(j(l));return e.json({sessions:o})}),i.get("/session",async e=>{let o=await O(e);return o?e.json(j(o)):e.json(p.sessionNotFound,404)}),i.post("/shutdown",async e=>{c("Shutdown request received, closing all sessions...");let o=[];for(let l of a.values())o.push(S(l));return await Promise.allSettled(o),c("All sessions closed, shutting down daemon server..."),setTimeout(()=>{process.exit(0)},500),e.json({status:"shutting_down"},200)}),i.post("/call",async e=>{try{y()&&await z(e);let o=await L(e);o.lastActiveAt=Date.now();let l=await e.req.json(),v=r[l.toolName];if(!v)return e.json(p.toolNotFound,404);let h;try{h=k.object(v.inputSchema()).parse(l.toolInput)}catch(g){let m=g.errors&&Array.isArray(g.errors)?g.errors.map(w=>`${w.path?.join(".")||"input"}: ${w.message}`).join("; "):"Invalid tool input";return e.json(f(400,`Invalid Tool Request: ${m}`),400)}try{let m={toolOutput:await o.toolExecutor.executeTool(v,h)};return e.json(m,200)}catch(g){let m={toolError:{code:g.code,message:g.message}};return e.json(m,500)}}catch(o){return d("Error occurred while handling tool call request",o),e.json(p.internalServerError,500)}}),i.delete("/session",async e=>{try{let o=await O(e);return o?(await S(o),e.json({ok:!0},200)):e.json(p.sessionNotFound,404)}catch(o){return d("Error occurred while deleting session",o),e.json(p.internalServerError,500)}}),i.onError((e,o)=>(d("Unhandled error in request handler",e),o.json({error:{code:500,message:"Internal Server Error"}},500))),i.notFound(e=>e.json({error:"Not Found",status:404},404)),M({fetch:i.fetch,port:n},()=>c(`Listening on port ${n}`)),U()}t(W,"startDaemonHTTPServer");var Z=import.meta.url===`file://${process.argv[1]}`||import.meta.url===`file://${process.argv[1]}.mjs`||process.argv[1]?.endsWith("daemon-server.js")||process.argv[1]?.endsWith("daemon-server.mjs");if(Z){let n=function(e){let o=Number(e);if(!Number.isInteger(o)||o<1||o>65535)throw new q("port must be an integer between 1 and 65535");return o};K=n,t(n,"parsePort");let s=new x().addOption(new _("--port <number>","port for daemon HTTP server").argParser(n).default(T)).allowUnknownOption().parse(process.argv).opts();C(),c("Starting daemon HTTP server..."),W(s.port).then(()=>{c("Daemon HTTP server started")}).catch(e=>{d("Failed to start daemon HTTP server",e),process.exit(1)})}var K;export{W as startDaemonHTTPServer};
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};