@graphty/remote-logger 0.0.1 → 1.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 (138) hide show
  1. package/README.md +944 -28
  2. package/bin/remote-log-server.js +3 -0
  3. package/dist/client/RemoteLogClient.d.ts +116 -0
  4. package/dist/client/RemoteLogClient.d.ts.map +1 -0
  5. package/dist/client/RemoteLogClient.js +269 -0
  6. package/dist/client/RemoteLogClient.js.map +1 -0
  7. package/dist/client/index.d.ts +7 -0
  8. package/dist/client/index.d.ts.map +1 -0
  9. package/dist/client/index.js +6 -0
  10. package/dist/client/index.js.map +1 -0
  11. package/dist/client/types.d.ts +60 -0
  12. package/dist/client/types.d.ts.map +1 -0
  13. package/dist/client/types.js +6 -0
  14. package/dist/client/types.js.map +1 -0
  15. package/dist/index.d.ts +22 -0
  16. package/dist/index.d.ts.map +1 -0
  17. package/dist/index.js +23 -0
  18. package/dist/index.js.map +1 -0
  19. package/dist/mcp/index.d.ts +9 -0
  20. package/dist/mcp/index.d.ts.map +1 -0
  21. package/dist/mcp/index.js +9 -0
  22. package/dist/mcp/index.js.map +1 -0
  23. package/dist/mcp/mcp-server.d.ts +32 -0
  24. package/dist/mcp/mcp-server.d.ts.map +1 -0
  25. package/dist/mcp/mcp-server.js +270 -0
  26. package/dist/mcp/mcp-server.js.map +1 -0
  27. package/dist/mcp/tools/index.d.ts +14 -0
  28. package/dist/mcp/tools/index.d.ts.map +1 -0
  29. package/dist/mcp/tools/index.js +14 -0
  30. package/dist/mcp/tools/index.js.map +1 -0
  31. package/dist/mcp/tools/logs-clear.d.ts +76 -0
  32. package/dist/mcp/tools/logs-clear.d.ts.map +1 -0
  33. package/dist/mcp/tools/logs-clear.js +58 -0
  34. package/dist/mcp/tools/logs-clear.js.map +1 -0
  35. package/dist/mcp/tools/logs-get-all.d.ts +60 -0
  36. package/dist/mcp/tools/logs-get-all.d.ts.map +1 -0
  37. package/dist/mcp/tools/logs-get-all.js +50 -0
  38. package/dist/mcp/tools/logs-get-all.js.map +1 -0
  39. package/dist/mcp/tools/logs-get-errors.d.ts +65 -0
  40. package/dist/mcp/tools/logs-get-errors.d.ts.map +1 -0
  41. package/dist/mcp/tools/logs-get-errors.js +46 -0
  42. package/dist/mcp/tools/logs-get-errors.js.map +1 -0
  43. package/dist/mcp/tools/logs-get-file-path.d.ts +75 -0
  44. package/dist/mcp/tools/logs-get-file-path.d.ts.map +1 -0
  45. package/dist/mcp/tools/logs-get-file-path.js +90 -0
  46. package/dist/mcp/tools/logs-get-file-path.js.map +1 -0
  47. package/dist/mcp/tools/logs-get-recent.d.ts +89 -0
  48. package/dist/mcp/tools/logs-get-recent.d.ts.map +1 -0
  49. package/dist/mcp/tools/logs-get-recent.js +74 -0
  50. package/dist/mcp/tools/logs-get-recent.js.map +1 -0
  51. package/dist/mcp/tools/logs-list-sessions.d.ts +64 -0
  52. package/dist/mcp/tools/logs-list-sessions.d.ts.map +1 -0
  53. package/dist/mcp/tools/logs-list-sessions.js +48 -0
  54. package/dist/mcp/tools/logs-list-sessions.js.map +1 -0
  55. package/dist/mcp/tools/logs-receive.d.ts +150 -0
  56. package/dist/mcp/tools/logs-receive.d.ts.map +1 -0
  57. package/dist/mcp/tools/logs-receive.js +68 -0
  58. package/dist/mcp/tools/logs-receive.js.map +1 -0
  59. package/dist/mcp/tools/logs-search.d.ts +91 -0
  60. package/dist/mcp/tools/logs-search.d.ts.map +1 -0
  61. package/dist/mcp/tools/logs-search.js +68 -0
  62. package/dist/mcp/tools/logs-search.js.map +1 -0
  63. package/dist/mcp/tools/logs-status.d.ts +45 -0
  64. package/dist/mcp/tools/logs-status.d.ts.map +1 -0
  65. package/dist/mcp/tools/logs-status.js +45 -0
  66. package/dist/mcp/tools/logs-status.js.map +1 -0
  67. package/dist/server/dual-server.d.ts +76 -0
  68. package/dist/server/dual-server.d.ts.map +1 -0
  69. package/dist/server/dual-server.js +214 -0
  70. package/dist/server/dual-server.js.map +1 -0
  71. package/dist/server/index.d.ts +12 -0
  72. package/dist/server/index.d.ts.map +1 -0
  73. package/dist/server/index.js +12 -0
  74. package/dist/server/index.js.map +1 -0
  75. package/dist/server/jsonl-writer.d.ts +93 -0
  76. package/dist/server/jsonl-writer.d.ts.map +1 -0
  77. package/dist/server/jsonl-writer.js +205 -0
  78. package/dist/server/jsonl-writer.js.map +1 -0
  79. package/dist/server/log-server.d.ts +126 -0
  80. package/dist/server/log-server.d.ts.map +1 -0
  81. package/dist/server/log-server.js +589 -0
  82. package/dist/server/log-server.js.map +1 -0
  83. package/dist/server/log-storage.d.ts +301 -0
  84. package/dist/server/log-storage.d.ts.map +1 -0
  85. package/dist/server/log-storage.js +408 -0
  86. package/dist/server/log-storage.js.map +1 -0
  87. package/dist/server/marker-utils.d.ts +69 -0
  88. package/dist/server/marker-utils.d.ts.map +1 -0
  89. package/dist/server/marker-utils.js +118 -0
  90. package/dist/server/marker-utils.js.map +1 -0
  91. package/dist/server/self-signed-cert.d.ts +30 -0
  92. package/dist/server/self-signed-cert.d.ts.map +1 -0
  93. package/dist/server/self-signed-cert.js +83 -0
  94. package/dist/server/self-signed-cert.js.map +1 -0
  95. package/dist/ui/ConsoleCaptureUI.d.ts +118 -0
  96. package/dist/ui/ConsoleCaptureUI.d.ts.map +1 -0
  97. package/dist/ui/ConsoleCaptureUI.js +571 -0
  98. package/dist/ui/ConsoleCaptureUI.js.map +1 -0
  99. package/dist/ui/index.d.ts +15 -0
  100. package/dist/ui/index.d.ts.map +1 -0
  101. package/dist/ui/index.js +15 -0
  102. package/dist/ui/index.js.map +1 -0
  103. package/dist/vite/index.d.ts +8 -0
  104. package/dist/vite/index.d.ts.map +1 -0
  105. package/dist/vite/index.js +8 -0
  106. package/dist/vite/index.js.map +1 -0
  107. package/dist/vite/plugin.d.ts +42 -0
  108. package/dist/vite/plugin.d.ts.map +1 -0
  109. package/dist/vite/plugin.js +46 -0
  110. package/dist/vite/plugin.js.map +1 -0
  111. package/package.json +90 -7
  112. package/src/client/RemoteLogClient.ts +328 -0
  113. package/src/client/index.ts +7 -0
  114. package/src/client/types.ts +62 -0
  115. package/src/index.ts +28 -0
  116. package/src/mcp/index.ts +25 -0
  117. package/src/mcp/mcp-server.ts +364 -0
  118. package/src/mcp/tools/index.ts +69 -0
  119. package/src/mcp/tools/logs-clear.ts +86 -0
  120. package/src/mcp/tools/logs-get-all.ts +78 -0
  121. package/src/mcp/tools/logs-get-errors.ts +71 -0
  122. package/src/mcp/tools/logs-get-file-path.ts +121 -0
  123. package/src/mcp/tools/logs-get-recent.ts +104 -0
  124. package/src/mcp/tools/logs-list-sessions.ts +71 -0
  125. package/src/mcp/tools/logs-receive.ts +96 -0
  126. package/src/mcp/tools/logs-search.ts +95 -0
  127. package/src/mcp/tools/logs-status.ts +69 -0
  128. package/src/server/dual-server.ts +308 -0
  129. package/src/server/index.ts +54 -0
  130. package/src/server/jsonl-writer.ts +277 -0
  131. package/src/server/log-server.ts +763 -0
  132. package/src/server/log-storage.ts +651 -0
  133. package/src/server/marker-utils.ts +144 -0
  134. package/src/server/self-signed-cert.ts +93 -0
  135. package/src/ui/ConsoleCaptureUI.ts +649 -0
  136. package/src/ui/index.ts +15 -0
  137. package/src/vite/index.ts +8 -0
  138. package/src/vite/plugin.ts +59 -0
@@ -0,0 +1,408 @@
1
+ /**
2
+ * Shared log storage with session metadata support.
3
+ *
4
+ * This module provides a centralized storage for logs that can be shared
5
+ * between HTTP and MCP interfaces. It supports project markers for
6
+ * filtering logs by git worktree or project.
7
+ * @module server/log-storage
8
+ */
9
+ import { extractMarkerFromSessionId } from "./marker-utils.js";
10
+ /**
11
+ * Default retention period in days.
12
+ */
13
+ const DEFAULT_RETENTION_DAYS = 7;
14
+ /**
15
+ * Default cleanup interval in milliseconds (1 hour).
16
+ */
17
+ const DEFAULT_CLEANUP_INTERVAL_MS = 60 * 60 * 1000;
18
+ /**
19
+ * Shared log storage with session metadata support.
20
+ *
21
+ * Provides methods for storing, querying, and managing logs across
22
+ * multiple sessions with support for project marker filtering.
23
+ */
24
+ export class LogStorage {
25
+ /**
26
+ * Create a new LogStorage instance.
27
+ * @param options - Optional configuration including JSONL writer
28
+ */
29
+ constructor(options = {}) {
30
+ this.sessions = new Map();
31
+ this.startTime = Date.now();
32
+ this.jsonlWriter = options.jsonlWriter;
33
+ // Determine retention days from options, env var, or default
34
+ const envRetention = process.env.REMOTE_LOG_RETENTION_DAYS;
35
+ this.retentionDays = options.retentionDays
36
+ ?? (envRetention ? parseInt(envRetention, 10) : undefined)
37
+ ?? DEFAULT_RETENTION_DAYS;
38
+ // Start periodic cleanup timer
39
+ const cleanupInterval = options.cleanupIntervalMs ?? DEFAULT_CLEANUP_INTERVAL_MS;
40
+ if (cleanupInterval > 0) {
41
+ this.cleanupTimer = setInterval(() => {
42
+ this.cleanupExpiredLogs();
43
+ }, cleanupInterval);
44
+ // Don't prevent process exit
45
+ this.cleanupTimer.unref?.();
46
+ }
47
+ }
48
+ /**
49
+ * Get the JSONL writer if configured.
50
+ * @returns The JSONL writer or undefined
51
+ */
52
+ getJsonlWriter() {
53
+ return this.jsonlWriter;
54
+ }
55
+ /**
56
+ * Add logs to storage for a session.
57
+ * @param sessionId - Unique identifier for the session
58
+ * @param logs - Array of log entries to add
59
+ * @param options - Additional options (projectMarker, worktreePath, pageUrl)
60
+ */
61
+ addLogs(sessionId, logs, options = {}) {
62
+ let sessionData = this.sessions.get(sessionId);
63
+ // Determine project marker for new sessions
64
+ const projectMarker = options.projectMarker || extractMarkerFromSessionId(sessionId);
65
+ if (!sessionData) {
66
+ // Create new session
67
+ sessionData = {
68
+ metadata: {
69
+ sessionId,
70
+ projectMarker,
71
+ worktreePath: options.worktreePath,
72
+ pageUrl: options.pageUrl,
73
+ firstLogTime: logs[0]?.time || new Date().toISOString(),
74
+ lastLogTime: logs[0]?.time || new Date().toISOString(),
75
+ logCount: 0,
76
+ errorCount: 0,
77
+ },
78
+ logs: [],
79
+ };
80
+ this.sessions.set(sessionId, sessionData);
81
+ }
82
+ // Add logs and update metadata
83
+ for (const log of logs) {
84
+ sessionData.logs.push(log);
85
+ sessionData.metadata.logCount++;
86
+ sessionData.metadata.lastLogTime = log.time;
87
+ if (log.level.toUpperCase() === "ERROR") {
88
+ sessionData.metadata.errorCount++;
89
+ }
90
+ // Write to JSONL file if writer is configured
91
+ if (this.jsonlWriter) {
92
+ // Use the session's project marker
93
+ const marker = sessionData.metadata.projectMarker;
94
+ void this.jsonlWriter.write(marker, {
95
+ time: log.time,
96
+ level: log.level,
97
+ message: log.message,
98
+ sessionId,
99
+ data: log.data,
100
+ });
101
+ }
102
+ }
103
+ // Update optional metadata if provided
104
+ if (options.worktreePath && !sessionData.metadata.worktreePath) {
105
+ sessionData.metadata.worktreePath = options.worktreePath;
106
+ }
107
+ if (options.pageUrl && !sessionData.metadata.pageUrl) {
108
+ sessionData.metadata.pageUrl = options.pageUrl;
109
+ }
110
+ }
111
+ /**
112
+ * Get logs with optional filtering.
113
+ * @param filter - Filter options
114
+ * @returns Array of log entries with session IDs
115
+ */
116
+ getLogs(filter = {}) {
117
+ const results = [];
118
+ for (const [sessionId, sessionData] of this.sessions) {
119
+ // Filter by project marker
120
+ if (filter.projectMarker && sessionData.metadata.projectMarker !== filter.projectMarker) {
121
+ continue;
122
+ }
123
+ // Filter by session ID
124
+ if (filter.sessionId && sessionId !== filter.sessionId) {
125
+ continue;
126
+ }
127
+ for (const log of sessionData.logs) {
128
+ // Filter by level
129
+ if (filter.level && log.level.toUpperCase() !== filter.level.toUpperCase()) {
130
+ continue;
131
+ }
132
+ // Filter by since
133
+ if (filter.since && new Date(log.time) <= new Date(filter.since)) {
134
+ continue;
135
+ }
136
+ results.push({ ...log, sessionId });
137
+ }
138
+ }
139
+ return results;
140
+ }
141
+ /**
142
+ * Get the most recent logs across all sessions.
143
+ * @param count - Maximum number of logs to return
144
+ * @param filter - Optional filter to apply before limiting
145
+ * @returns Array of recent log entries (oldest first)
146
+ */
147
+ getRecentLogs(count, filter = {}) {
148
+ const allLogs = this.getLogs(filter);
149
+ // Sort by time descending (newest first)
150
+ allLogs.sort((a, b) => new Date(b.time).getTime() - new Date(a.time).getTime());
151
+ // Take the most recent 'count' logs, then reverse to show oldest first
152
+ return allLogs.slice(0, count).reverse();
153
+ }
154
+ /**
155
+ * Get only ERROR level logs.
156
+ * @param filter - Optional filter options
157
+ * @returns Array of error log entries
158
+ */
159
+ getErrors(filter = {}) {
160
+ const logs = this.getLogs({ ...filter, level: "ERROR" });
161
+ // Sort chronologically
162
+ return logs.sort((a, b) => new Date(a.time).getTime() - new Date(b.time).getTime());
163
+ }
164
+ /**
165
+ * Get all sessions with their metadata.
166
+ * @param filter - Optional filter options
167
+ * @returns Array of session metadata
168
+ */
169
+ getSessions(filter = {}) {
170
+ const results = [];
171
+ for (const sessionData of this.sessions.values()) {
172
+ // Filter by project marker
173
+ if (filter.projectMarker && sessionData.metadata.projectMarker !== filter.projectMarker) {
174
+ continue;
175
+ }
176
+ // Filter by hasErrors
177
+ if (filter.hasErrors && sessionData.metadata.errorCount === 0) {
178
+ continue;
179
+ }
180
+ results.push({ ...sessionData.metadata });
181
+ }
182
+ return results;
183
+ }
184
+ /**
185
+ * Clear logs with optional filtering.
186
+ * @param filter - Optional filter to limit what is cleared
187
+ * @returns Object with count of cleared sessions
188
+ */
189
+ clearLogs(filter = {}) {
190
+ let cleared = 0;
191
+ if (!filter.projectMarker && !filter.sessionId) {
192
+ // Clear all
193
+ cleared = this.sessions.size;
194
+ this.sessions.clear();
195
+ }
196
+ else {
197
+ // Clear selectively
198
+ const toDelete = [];
199
+ for (const [sessionId, sessionData] of this.sessions) {
200
+ if (filter.sessionId && sessionId === filter.sessionId) {
201
+ toDelete.push(sessionId);
202
+ }
203
+ else if (filter.projectMarker && sessionData.metadata.projectMarker === filter.projectMarker) {
204
+ toDelete.push(sessionId);
205
+ }
206
+ }
207
+ for (const sessionId of toDelete) {
208
+ this.sessions.delete(sessionId);
209
+ cleared++;
210
+ }
211
+ }
212
+ return { cleared };
213
+ }
214
+ /**
215
+ * Clear all logs (convenience method).
216
+ */
217
+ clear() {
218
+ this.sessions.clear();
219
+ }
220
+ /**
221
+ * Set the HTTP server configuration.
222
+ * Call this after the HTTP server starts to make endpoint info available.
223
+ * @param config - Server configuration
224
+ */
225
+ setServerConfig(config) {
226
+ this.serverConfig = config;
227
+ }
228
+ /**
229
+ * Get the HTTP server configuration.
230
+ * @returns Server configuration or undefined if not set
231
+ */
232
+ getServerConfig() {
233
+ return this.serverConfig;
234
+ }
235
+ /**
236
+ * Get health status of the storage.
237
+ * @returns Health status object
238
+ */
239
+ getHealth() {
240
+ let totalLogs = 0;
241
+ let totalErrors = 0;
242
+ for (const sessionData of this.sessions.values()) {
243
+ totalLogs += sessionData.metadata.logCount;
244
+ totalErrors += sessionData.metadata.errorCount;
245
+ }
246
+ return {
247
+ status: "ok",
248
+ sessionCount: this.sessions.size,
249
+ totalLogs,
250
+ totalErrors,
251
+ uptimeMs: Date.now() - this.startTime,
252
+ };
253
+ }
254
+ /**
255
+ * Get full server status including health and configuration.
256
+ * @returns Server status object
257
+ */
258
+ getStatus() {
259
+ const health = this.getHealth();
260
+ return {
261
+ ...health,
262
+ server: this.serverConfig,
263
+ retentionDays: this.retentionDays,
264
+ };
265
+ }
266
+ /**
267
+ * Get logs for a specific session.
268
+ * @param sessionId - The session ID to get logs for
269
+ * @returns Array of log entries for the session
270
+ */
271
+ getLogsForSession(sessionId) {
272
+ const sessionData = this.sessions.get(sessionId);
273
+ return sessionData ? [...sessionData.logs] : [];
274
+ }
275
+ /**
276
+ * Get all logs grouped by session ID.
277
+ * @param filter - Optional filter options
278
+ * @param filter.projectMarker - Filter by project marker
279
+ * @returns Object mapping session IDs to log arrays
280
+ */
281
+ getAllLogsBySession(filter = {}) {
282
+ const result = {};
283
+ for (const [sessionId, sessionData] of this.sessions) {
284
+ if (filter.projectMarker && sessionData.metadata.projectMarker !== filter.projectMarker) {
285
+ continue;
286
+ }
287
+ result[sessionId] = [...sessionData.logs];
288
+ }
289
+ return result;
290
+ }
291
+ /**
292
+ * Search logs by content.
293
+ * @param options - Search options
294
+ * @returns Array of matching log entries
295
+ */
296
+ search(options) {
297
+ const { query, regex = false, projectMarker, level, limit = 100 } = options;
298
+ // Build the search pattern
299
+ let pattern;
300
+ try {
301
+ pattern = regex ? new RegExp(query, "i") : new RegExp(query.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "i");
302
+ }
303
+ catch {
304
+ // Invalid regex, return empty results
305
+ return [];
306
+ }
307
+ const results = [];
308
+ for (const [sessionId, sessionData] of this.sessions) {
309
+ // Filter by project marker
310
+ if (projectMarker && sessionData.metadata.projectMarker !== projectMarker) {
311
+ continue;
312
+ }
313
+ for (const log of sessionData.logs) {
314
+ // Filter by level
315
+ if (level && log.level.toUpperCase() !== level.toUpperCase()) {
316
+ continue;
317
+ }
318
+ // Test message against pattern
319
+ if (pattern.test(log.message)) {
320
+ results.push({ ...log, sessionId });
321
+ if (results.length >= limit) {
322
+ return results;
323
+ }
324
+ }
325
+ }
326
+ }
327
+ return results;
328
+ }
329
+ /**
330
+ * Check if a session exists.
331
+ * @param sessionId - The session ID to check
332
+ * @returns True if the session exists
333
+ */
334
+ hasSession(sessionId) {
335
+ return this.sessions.has(sessionId);
336
+ }
337
+ /**
338
+ * Get metadata for a specific session.
339
+ * @param sessionId - The session ID
340
+ * @returns Session metadata or undefined if not found
341
+ */
342
+ getSessionMetadata(sessionId) {
343
+ const sessionData = this.sessions.get(sessionId);
344
+ return sessionData ? { ...sessionData.metadata } : undefined;
345
+ }
346
+ /**
347
+ * Get the configured retention period in days.
348
+ * @returns Number of days logs are retained
349
+ */
350
+ getRetentionDays() {
351
+ return this.retentionDays;
352
+ }
353
+ /**
354
+ * Stop the periodic cleanup timer.
355
+ * Call this when shutting down to prevent memory leaks.
356
+ */
357
+ stopCleanupTimer() {
358
+ if (this.cleanupTimer) {
359
+ clearInterval(this.cleanupTimer);
360
+ this.cleanupTimer = undefined;
361
+ }
362
+ }
363
+ /**
364
+ * Clean up logs older than the retention period.
365
+ * This removes individual logs from sessions, removes sessions
366
+ * that have no remaining logs, and cleans up old JSONL files.
367
+ * @returns Number of sessions that were completely removed
368
+ */
369
+ cleanupExpiredLogs() {
370
+ const cutoffTime = new Date();
371
+ cutoffTime.setDate(cutoffTime.getDate() - this.retentionDays);
372
+ const cutoffMs = cutoffTime.getTime();
373
+ const sessionsToRemove = [];
374
+ for (const [sessionId, sessionData] of this.sessions) {
375
+ // Filter out expired logs
376
+ const remainingLogs = sessionData.logs.filter((log) => new Date(log.time).getTime() > cutoffMs);
377
+ if (remainingLogs.length === 0) {
378
+ // Session has no remaining logs, mark for removal
379
+ sessionsToRemove.push(sessionId);
380
+ }
381
+ else if (remainingLogs.length !== sessionData.logs.length) {
382
+ // Some logs were removed, update the session
383
+ sessionData.logs = remainingLogs;
384
+ // Recalculate metadata
385
+ let errorCount = 0;
386
+ for (const log of remainingLogs) {
387
+ if (log.level.toUpperCase() === "ERROR") {
388
+ errorCount++;
389
+ }
390
+ }
391
+ sessionData.metadata.logCount = remainingLogs.length;
392
+ sessionData.metadata.errorCount = errorCount;
393
+ sessionData.metadata.firstLogTime = remainingLogs[0].time;
394
+ sessionData.metadata.lastLogTime = remainingLogs[remainingLogs.length - 1].time;
395
+ }
396
+ }
397
+ // Remove empty sessions
398
+ for (const sessionId of sessionsToRemove) {
399
+ this.sessions.delete(sessionId);
400
+ }
401
+ // Clean up old JSONL files
402
+ if (this.jsonlWriter) {
403
+ this.jsonlWriter.cleanupOldFiles(this.retentionDays);
404
+ }
405
+ return sessionsToRemove.length;
406
+ }
407
+ }
408
+ //# sourceMappingURL=log-storage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log-storage.js","sourceRoot":"","sources":["../../src/server/log-storage.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Utilities for extracting and resolving project markers.
3
+ *
4
+ * Project markers are used to identify which git worktree or project
5
+ * a log session belongs to, enabling filtering of logs by project.
6
+ * @module server/marker-utils
7
+ */
8
+ /**
9
+ * Extract a project marker from a filesystem path.
10
+ *
11
+ * The function looks for `.worktrees` in the path and extracts the worktree name.
12
+ * If no worktree is found, it falls back to the directory basename.
13
+ * @param cwd - The filesystem path to extract a marker from
14
+ * @returns The extracted project marker, or "default" if extraction fails
15
+ * @example
16
+ * // Worktree paths
17
+ * extractMarkerFromPath("/home/user/.worktrees/remote-logging") // "remote-logging"
18
+ * extractMarkerFromPath("C:\\Users\\dev\\.worktrees\\feature-xyz") // "feature-xyz"
19
+ *
20
+ * // Regular paths (uses basename)
21
+ * extractMarkerFromPath("/home/user/my-project") // "my-project"
22
+ */
23
+ export declare function extractMarkerFromPath(cwd: string): string;
24
+ /**
25
+ * Extract a project marker from a session ID.
26
+ *
27
+ * Session IDs typically follow the format: {prefix}-{timestamp}-{random}
28
+ * This function extracts the prefix part as the project marker.
29
+ * @param sessionId - The session ID to extract a marker from
30
+ * @returns The extracted project marker, or "default" if extraction fails
31
+ * @example
32
+ * extractMarkerFromSessionId("graphty-element-1704067200000-abc123") // "graphty-element"
33
+ * extractMarkerFromSessionId("my-app-1704067200000-xyz") // "my-app"
34
+ * extractMarkerFromSessionId("simple") // "simple"
35
+ */
36
+ export declare function extractMarkerFromSessionId(sessionId: string): string;
37
+ /**
38
+ * Options for resolving a project marker.
39
+ */
40
+ export interface MarkerResolutionOptions {
41
+ /** Explicit project marker (highest priority) */
42
+ projectMarker?: string;
43
+ /** Working directory path to extract marker from */
44
+ workingDirectory?: string;
45
+ /** Session ID to extract marker from (lowest priority) */
46
+ sessionId?: string;
47
+ }
48
+ /**
49
+ * Resolve a project marker using a fallback chain.
50
+ *
51
+ * Priority order:
52
+ * 1. Explicit projectMarker parameter
53
+ * 2. Extracted from workingDirectory path
54
+ * 3. Extracted from sessionId
55
+ * 4. "default" as final fallback
56
+ * @param options - Resolution options with various marker sources
57
+ * @returns The resolved project marker
58
+ * @example
59
+ * resolveProjectMarker({
60
+ * projectMarker: "explicit",
61
+ * workingDirectory: "/path/to/.worktrees/from-path"
62
+ * }) // "explicit"
63
+ *
64
+ * resolveProjectMarker({
65
+ * workingDirectory: "/path/to/.worktrees/remote-logging"
66
+ * }) // "remote-logging"
67
+ */
68
+ export declare function resolveProjectMarker(options: MarkerResolutionOptions): string;
69
+ //# sourceMappingURL=marker-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"marker-utils.d.ts","sourceRoot":"","sources":["../../src/server/marker-utils.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAwBzD;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,0BAA0B,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAuBpE;AAED;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACpC,iDAAiD;IACjD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,oDAAoD;IACpD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,0DAA0D;IAC1D,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,uBAAuB,GAAG,MAAM,CAwB7E"}
@@ -0,0 +1,118 @@
1
+ /**
2
+ * Utilities for extracting and resolving project markers.
3
+ *
4
+ * Project markers are used to identify which git worktree or project
5
+ * a log session belongs to, enabling filtering of logs by project.
6
+ * @module server/marker-utils
7
+ */
8
+ /**
9
+ * Extract a project marker from a filesystem path.
10
+ *
11
+ * The function looks for `.worktrees` in the path and extracts the worktree name.
12
+ * If no worktree is found, it falls back to the directory basename.
13
+ * @param cwd - The filesystem path to extract a marker from
14
+ * @returns The extracted project marker, or "default" if extraction fails
15
+ * @example
16
+ * // Worktree paths
17
+ * extractMarkerFromPath("/home/user/.worktrees/remote-logging") // "remote-logging"
18
+ * extractMarkerFromPath("C:\\Users\\dev\\.worktrees\\feature-xyz") // "feature-xyz"
19
+ *
20
+ * // Regular paths (uses basename)
21
+ * extractMarkerFromPath("/home/user/my-project") // "my-project"
22
+ */
23
+ export function extractMarkerFromPath(cwd) {
24
+ if (!cwd || cwd === "/") {
25
+ return "default";
26
+ }
27
+ // Normalize trailing slashes
28
+ const normalizedPath = cwd.replace(/[/\\]+$/, "");
29
+ if (!normalizedPath) {
30
+ return "default";
31
+ }
32
+ // Check if in .worktrees directory (supports both Unix and Windows paths)
33
+ // Match: .worktrees/worktree-name or .worktrees\worktree-name
34
+ const worktreeMatch = normalizedPath.match(/\.worktrees[/\\]([^/\\]+)/);
35
+ if (worktreeMatch) {
36
+ return worktreeMatch[1];
37
+ }
38
+ // Fall back to directory name
39
+ // Handle both Unix and Windows paths by splitting on both separators
40
+ const segments = normalizedPath.split(/[/\\]/);
41
+ const basename = segments.filter(Boolean).pop();
42
+ return basename || "default";
43
+ }
44
+ /**
45
+ * Extract a project marker from a session ID.
46
+ *
47
+ * Session IDs typically follow the format: {prefix}-{timestamp}-{random}
48
+ * This function extracts the prefix part as the project marker.
49
+ * @param sessionId - The session ID to extract a marker from
50
+ * @returns The extracted project marker, or "default" if extraction fails
51
+ * @example
52
+ * extractMarkerFromSessionId("graphty-element-1704067200000-abc123") // "graphty-element"
53
+ * extractMarkerFromSessionId("my-app-1704067200000-xyz") // "my-app"
54
+ * extractMarkerFromSessionId("simple") // "simple"
55
+ */
56
+ export function extractMarkerFromSessionId(sessionId) {
57
+ if (!sessionId) {
58
+ return "default";
59
+ }
60
+ // Session IDs follow format: {prefix}-{timestamp}-{random}
61
+ // The timestamp is typically a 13-digit number (milliseconds since epoch)
62
+ // We want to extract everything before the timestamp
63
+ // Look for pattern: name-{13 digits}-{suffix}
64
+ const timestampMatch = sessionId.match(/^(.+?)-(\d{10,13})-[a-zA-Z0-9]+$/);
65
+ if (timestampMatch) {
66
+ return timestampMatch[1];
67
+ }
68
+ // Fall back to first segment before hyphen
69
+ const firstHyphen = sessionId.indexOf("-");
70
+ if (firstHyphen > 0) {
71
+ return sessionId.substring(0, firstHyphen);
72
+ }
73
+ // Return the whole session ID if no hyphen
74
+ return sessionId;
75
+ }
76
+ /**
77
+ * Resolve a project marker using a fallback chain.
78
+ *
79
+ * Priority order:
80
+ * 1. Explicit projectMarker parameter
81
+ * 2. Extracted from workingDirectory path
82
+ * 3. Extracted from sessionId
83
+ * 4. "default" as final fallback
84
+ * @param options - Resolution options with various marker sources
85
+ * @returns The resolved project marker
86
+ * @example
87
+ * resolveProjectMarker({
88
+ * projectMarker: "explicit",
89
+ * workingDirectory: "/path/to/.worktrees/from-path"
90
+ * }) // "explicit"
91
+ *
92
+ * resolveProjectMarker({
93
+ * workingDirectory: "/path/to/.worktrees/remote-logging"
94
+ * }) // "remote-logging"
95
+ */
96
+ export function resolveProjectMarker(options) {
97
+ // Priority 1: Explicit project marker
98
+ if (options.projectMarker) {
99
+ return options.projectMarker;
100
+ }
101
+ // Priority 2: Extract from working directory
102
+ if (options.workingDirectory) {
103
+ const fromPath = extractMarkerFromPath(options.workingDirectory);
104
+ if (fromPath !== "default") {
105
+ return fromPath;
106
+ }
107
+ }
108
+ // Priority 3: Extract from session ID
109
+ if (options.sessionId) {
110
+ const fromSession = extractMarkerFromSessionId(options.sessionId);
111
+ if (fromSession !== "default") {
112
+ return fromSession;
113
+ }
114
+ }
115
+ // Final fallback
116
+ return "default";
117
+ }
118
+ //# sourceMappingURL=marker-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"marker-utils.js","sourceRoot":"","sources":["../../src/server/marker-utils.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,qBAAqB,CAAC,GAAW;IAC7C,IAAI,CAAC,GAAG,IAAI,GAAG,KAAK,GAAG,EAAE,CAAC;QACtB,OAAO,SAAS,CAAC;IACrB,CAAC;IAED,6BAA6B;IAC7B,MAAM,cAAc,GAAG,GAAG,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;IAElD,IAAI,CAAC,cAAc,EAAE,CAAC;QAClB,OAAO,SAAS,CAAC;IACrB,CAAC;IAED,0EAA0E;IAC1E,8DAA8D;IAC9D,MAAM,aAAa,GAAG,cAAc,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAC;IACxE,IAAI,aAAa,EAAE,CAAC;QAChB,OAAO,aAAa,CAAC,CAAC,CAAC,CAAC;IAC5B,CAAC;IAED,8BAA8B;IAC9B,qEAAqE;IACrE,MAAM,QAAQ,GAAG,cAAc,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC/C,MAAM,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,CAAC;IAChD,OAAO,QAAQ,IAAI,SAAS,CAAC;AACjC,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,0BAA0B,CAAC,SAAiB;IACxD,IAAI,CAAC,SAAS,EAAE,CAAC;QACb,OAAO,SAAS,CAAC;IACrB,CAAC;IAED,2DAA2D;IAC3D,0EAA0E;IAC1E,qDAAqD;IAErD,8CAA8C;IAC9C,MAAM,cAAc,GAAG,SAAS,CAAC,KAAK,CAAC,kCAAkC,CAAC,CAAC;IAC3E,IAAI,cAAc,EAAE,CAAC;QACjB,OAAO,cAAc,CAAC,CAAC,CAAC,CAAC;IAC7B,CAAC;IAED,2CAA2C;IAC3C,MAAM,WAAW,GAAG,SAAS,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAC3C,IAAI,WAAW,GAAG,CAAC,EAAE,CAAC;QAClB,OAAO,SAAS,CAAC,SAAS,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC;IAC/C,CAAC;IAED,2CAA2C;IAC3C,OAAO,SAAS,CAAC;AACrB,CAAC;AAcD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,oBAAoB,CAAC,OAAgC;IACjE,sCAAsC;IACtC,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC;QACxB,OAAO,OAAO,CAAC,aAAa,CAAC;IACjC,CAAC;IAED,6CAA6C;IAC7C,IAAI,OAAO,CAAC,gBAAgB,EAAE,CAAC;QAC3B,MAAM,QAAQ,GAAG,qBAAqB,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;QACjE,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;YACzB,OAAO,QAAQ,CAAC;QACpB,CAAC;IACL,CAAC;IAED,sCAAsC;IACtC,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;QACpB,MAAM,WAAW,GAAG,0BAA0B,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QAClE,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;YAC5B,OAAO,WAAW,CAAC;QACvB,CAAC;IACL,CAAC;IAED,iBAAiB;IACjB,OAAO,SAAS,CAAC;AACrB,CAAC"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Self-signed certificate generation for the log server.
3
+ * Uses the 'selfsigned' npm package to generate proper X.509 certificates.
4
+ */
5
+ export interface GeneratedCert {
6
+ cert: string;
7
+ key: string;
8
+ }
9
+ /**
10
+ * Generate a self-signed certificate for HTTPS.
11
+ * The certificate is valid for localhost and common local development hostnames.
12
+ * @param hostname - Optional hostname to include in the certificate (default: localhost)
13
+ * @returns Object containing PEM-encoded certificate and private key
14
+ */
15
+ export declare function generateSelfSignedCert(hostname?: string): GeneratedCert;
16
+ /**
17
+ * Check if certificate files exist and are readable.
18
+ * @param certPath - Path to the certificate file
19
+ * @param keyPath - Path to the private key file
20
+ * @returns true if both files exist and are readable
21
+ */
22
+ export declare function certFilesExist(certPath: string, keyPath: string): boolean;
23
+ /**
24
+ * Read certificate and key from files.
25
+ * @param certPath - Path to the certificate file
26
+ * @param keyPath - Path to the private key file
27
+ * @returns Object containing PEM-encoded certificate and private key
28
+ */
29
+ export declare function readCertFiles(certPath: string, keyPath: string): GeneratedCert;
30
+ //# sourceMappingURL=self-signed-cert.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"self-signed-cert.d.ts","sourceRoot":"","sources":["../../src/server/self-signed-cert.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,MAAM,WAAW,aAAa;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;CACf;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,QAAQ,SAAc,GAAG,aAAa,CA4C5E;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAQzE;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,aAAa,CAK9E"}