@dollhousemcp/mcp-server 2.0.0 → 2.0.1
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/README.md +282 -222
- package/README.npm.md +282 -222
- package/dist/constants/version.d.ts +3 -0
- package/dist/constants/version.d.ts.map +1 -0
- package/dist/constants/version.js +4 -0
- package/dist/generated/version.d.ts +2 -2
- package/dist/generated/version.js +3 -3
- package/dist/logging/sinks/SSELogSink.d.ts +35 -0
- package/dist/logging/sinks/SSELogSink.d.ts.map +1 -0
- package/dist/logging/sinks/SSELogSink.js +181 -0
- package/dist/logging/viewer/viewerHtml.d.ts +8 -0
- package/dist/logging/viewer/viewerHtml.d.ts.map +1 -0
- package/dist/logging/viewer/viewerHtml.js +204 -0
- package/package.json +1 -1
- package/server.json +2 -2
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* Auto-generated file - DO NOT EDIT
|
|
3
3
|
* Generated at build time by scripts/generate-version.js
|
|
4
4
|
*/
|
|
5
|
-
export const PACKAGE_VERSION = '2.0.
|
|
6
|
-
export const BUILD_TIMESTAMP = '2026-04-
|
|
5
|
+
export const PACKAGE_VERSION = '2.0.1';
|
|
6
|
+
export const BUILD_TIMESTAMP = '2026-04-02T00:00:54.478Z';
|
|
7
7
|
export const BUILD_TYPE = 'npm';
|
|
8
8
|
export const PACKAGE_NAME = '@dollhousemcp/mcp-server';
|
|
9
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
9
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmVyc2lvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9nZW5lcmF0ZWQvdmVyc2lvbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7O0dBR0c7QUFFSCxNQUFNLENBQUMsTUFBTSxlQUFlLEdBQUcsT0FBTyxDQUFDO0FBQ3ZDLE1BQU0sQ0FBQyxNQUFNLGVBQWUsR0FBRywwQkFBMEIsQ0FBQztBQUMxRCxNQUFNLENBQUMsTUFBTSxVQUFVLEdBQWtCLEtBQUssQ0FBQztBQUMvQyxNQUFNLENBQUMsTUFBTSxZQUFZLEdBQUcsMEJBQTBCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEF1dG8tZ2VuZXJhdGVkIGZpbGUgLSBETyBOT1QgRURJVFxuICogR2VuZXJhdGVkIGF0IGJ1aWxkIHRpbWUgYnkgc2NyaXB0cy9nZW5lcmF0ZS12ZXJzaW9uLmpzXG4gKi9cblxuZXhwb3J0IGNvbnN0IFBBQ0tBR0VfVkVSU0lPTiA9ICcyLjAuMSc7XG5leHBvcnQgY29uc3QgQlVJTERfVElNRVNUQU1QID0gJzIwMjYtMDQtMDJUMDA6MDA6NTQuNDc4Wic7XG5leHBvcnQgY29uc3QgQlVJTERfVFlQRTogJ25wbScgfCAnZ2l0JyA9ICducG0nO1xuZXhwb3J0IGNvbnN0IFBBQ0tBR0VfTkFNRSA9ICdAZG9sbGhvdXNlbWNwL21jcC1zZXJ2ZXInO1xuIl19
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SSE-based real-time log viewer sink.
|
|
3
|
+
*
|
|
4
|
+
* Implements ILogSink and runs an opt-in Express HTTP server that:
|
|
5
|
+
* - Serves a browser-based log viewer at GET /
|
|
6
|
+
* - Streams log entries via SSE at GET /logs/stream
|
|
7
|
+
* - Exposes a JSON query endpoint at GET /logs (delegates to MemoryLogSink)
|
|
8
|
+
* - Provides a health endpoint at GET /health
|
|
9
|
+
*
|
|
10
|
+
* See docs/LOGGING-DESIGN.md §4.6 for the full design.
|
|
11
|
+
*/
|
|
12
|
+
import type { ILogSink, UnifiedLogEntry } from '../types.js';
|
|
13
|
+
import type { MemoryLogSink } from './MemoryLogSink.js';
|
|
14
|
+
export interface SSELogSinkOptions {
|
|
15
|
+
port: number;
|
|
16
|
+
memorySink: MemoryLogSink;
|
|
17
|
+
}
|
|
18
|
+
export declare class SSELogSink implements ILogSink {
|
|
19
|
+
private readonly app;
|
|
20
|
+
private server;
|
|
21
|
+
private readonly clients;
|
|
22
|
+
private readonly memorySink;
|
|
23
|
+
private readonly port;
|
|
24
|
+
private readonly startTime;
|
|
25
|
+
constructor(options: SSELogSinkOptions);
|
|
26
|
+
write(entry: UnifiedLogEntry): void;
|
|
27
|
+
flush(): Promise<void>;
|
|
28
|
+
close(): Promise<void>;
|
|
29
|
+
start(): Promise<void>;
|
|
30
|
+
get clientCount(): number;
|
|
31
|
+
getPort(): number;
|
|
32
|
+
private setupRoutes;
|
|
33
|
+
private matchesFilter;
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=SSELogSink.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SSELogSink.d.ts","sourceRoot":"","sources":["../../../src/logging/sinks/SSELogSink.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAKH,OAAO,KAAK,EAAE,QAAQ,EAAE,eAAe,EAAyB,MAAM,aAAa,CAAC;AAEpF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAGxD,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,aAAa,CAAC;CAC3B;AAcD,qBAAa,UAAW,YAAW,QAAQ;IACzC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAA6B;IACjD,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAwB;IAChD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAgB;IAC3C,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;IAC9B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAc;gBAE5B,OAAO,EAAE,iBAAiB;IAWtC,KAAK,CAAC,KAAK,EAAE,eAAe,GAAG,IAAI;IAQ7B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAItB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAoBtB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAS5B,IAAI,WAAW,IAAI,MAAM,CAExB;IAED,OAAO,IAAI,MAAM;IAWjB,OAAO,CAAC,WAAW;IA4FnB,OAAO,CAAC,aAAa;CAkBtB"}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SSE-based real-time log viewer sink.
|
|
3
|
+
*
|
|
4
|
+
* Implements ILogSink and runs an opt-in Express HTTP server that:
|
|
5
|
+
* - Serves a browser-based log viewer at GET /
|
|
6
|
+
* - Streams log entries via SSE at GET /logs/stream
|
|
7
|
+
* - Exposes a JSON query endpoint at GET /logs (delegates to MemoryLogSink)
|
|
8
|
+
* - Provides a health endpoint at GET /health
|
|
9
|
+
*
|
|
10
|
+
* See docs/LOGGING-DESIGN.md §4.6 for the full design.
|
|
11
|
+
*/
|
|
12
|
+
import express from 'express';
|
|
13
|
+
import { LOG_LEVEL_PRIORITY } from '../types.js';
|
|
14
|
+
import { getViewerHtml } from '../viewer/viewerHtml.js';
|
|
15
|
+
export class SSELogSink {
|
|
16
|
+
app;
|
|
17
|
+
server = null;
|
|
18
|
+
clients = new Set();
|
|
19
|
+
memorySink;
|
|
20
|
+
port;
|
|
21
|
+
startTime = Date.now();
|
|
22
|
+
constructor(options) {
|
|
23
|
+
this.port = options.port;
|
|
24
|
+
this.memorySink = options.memorySink;
|
|
25
|
+
this.app = express();
|
|
26
|
+
this.setupRoutes();
|
|
27
|
+
}
|
|
28
|
+
// ---------------------------------------------------------------------------
|
|
29
|
+
// ILogSink
|
|
30
|
+
// ---------------------------------------------------------------------------
|
|
31
|
+
write(entry) {
|
|
32
|
+
for (const client of this.clients) {
|
|
33
|
+
if (this.matchesFilter(entry, client.filter)) {
|
|
34
|
+
client.res.write(`data: ${JSON.stringify(entry)}\n\n`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
async flush() {
|
|
39
|
+
// No-op — SSE writes are immediate.
|
|
40
|
+
}
|
|
41
|
+
async close() {
|
|
42
|
+
// End all client connections
|
|
43
|
+
for (const client of this.clients) {
|
|
44
|
+
client.res.end();
|
|
45
|
+
}
|
|
46
|
+
this.clients.clear();
|
|
47
|
+
// Shut down HTTP server
|
|
48
|
+
if (this.server) {
|
|
49
|
+
await new Promise((resolve) => {
|
|
50
|
+
this.server.close(() => resolve());
|
|
51
|
+
});
|
|
52
|
+
this.server = null;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
// ---------------------------------------------------------------------------
|
|
56
|
+
// Lifecycle
|
|
57
|
+
// ---------------------------------------------------------------------------
|
|
58
|
+
async start() {
|
|
59
|
+
return new Promise((resolve) => {
|
|
60
|
+
this.server = this.app.listen(this.port, '127.0.0.1', () => {
|
|
61
|
+
this.server.unref();
|
|
62
|
+
resolve();
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
get clientCount() {
|
|
67
|
+
return this.clients.size;
|
|
68
|
+
}
|
|
69
|
+
getPort() {
|
|
70
|
+
if (!this.server)
|
|
71
|
+
return this.port;
|
|
72
|
+
const addr = this.server.address();
|
|
73
|
+
if (addr && typeof addr === 'object')
|
|
74
|
+
return addr.port;
|
|
75
|
+
return this.port;
|
|
76
|
+
}
|
|
77
|
+
// ---------------------------------------------------------------------------
|
|
78
|
+
// Routes
|
|
79
|
+
// ---------------------------------------------------------------------------
|
|
80
|
+
setupRoutes() {
|
|
81
|
+
// Viewer HTML
|
|
82
|
+
this.app.get('/', (_req, res) => {
|
|
83
|
+
const actualPort = this.getPort();
|
|
84
|
+
res.type('html').send(getViewerHtml(actualPort));
|
|
85
|
+
});
|
|
86
|
+
// SSE stream
|
|
87
|
+
this.app.get('/logs/stream', (req, res) => {
|
|
88
|
+
res.writeHead(200, {
|
|
89
|
+
'Content-Type': 'text/event-stream',
|
|
90
|
+
'Cache-Control': 'no-cache',
|
|
91
|
+
'Connection': 'keep-alive',
|
|
92
|
+
});
|
|
93
|
+
res.write(':connected\n\n');
|
|
94
|
+
const filter = {};
|
|
95
|
+
if (typeof req.query['category'] === 'string' && req.query['category']) {
|
|
96
|
+
filter.category = req.query['category'];
|
|
97
|
+
}
|
|
98
|
+
if (typeof req.query['level'] === 'string' && req.query['level']) {
|
|
99
|
+
filter.level = req.query['level'];
|
|
100
|
+
}
|
|
101
|
+
if (typeof req.query['source'] === 'string' && req.query['source']) {
|
|
102
|
+
filter.source = req.query['source'];
|
|
103
|
+
}
|
|
104
|
+
if (typeof req.query['correlationId'] === 'string' && req.query['correlationId']) {
|
|
105
|
+
filter.correlationId = req.query['correlationId'];
|
|
106
|
+
}
|
|
107
|
+
const client = { res, filter };
|
|
108
|
+
this.clients.add(client);
|
|
109
|
+
// Backfill recent history so the viewer shows context on connect
|
|
110
|
+
const history = this.memorySink.query({ category: 'all', limit: 500 });
|
|
111
|
+
// Send oldest-first so the viewer displays in chronological order
|
|
112
|
+
const entries = history.entries.slice().reverse();
|
|
113
|
+
for (const entry of entries) {
|
|
114
|
+
res.write(`data: ${JSON.stringify(entry)}\n\n`);
|
|
115
|
+
}
|
|
116
|
+
req.on('close', () => {
|
|
117
|
+
this.clients.delete(client);
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
// JSON query (delegates to MemoryLogSink)
|
|
121
|
+
this.app.get('/logs', (req, res) => {
|
|
122
|
+
const options = {};
|
|
123
|
+
if (typeof req.query['category'] === 'string' && req.query['category']) {
|
|
124
|
+
options['category'] = req.query['category'];
|
|
125
|
+
}
|
|
126
|
+
if (typeof req.query['level'] === 'string' && req.query['level']) {
|
|
127
|
+
options['level'] = req.query['level'];
|
|
128
|
+
}
|
|
129
|
+
if (typeof req.query['source'] === 'string' && req.query['source']) {
|
|
130
|
+
options['source'] = req.query['source'];
|
|
131
|
+
}
|
|
132
|
+
if (typeof req.query['message'] === 'string' && req.query['message']) {
|
|
133
|
+
options['message'] = req.query['message'];
|
|
134
|
+
}
|
|
135
|
+
if (typeof req.query['limit'] === 'string') {
|
|
136
|
+
options['limit'] = parseInt(req.query['limit'], 10);
|
|
137
|
+
}
|
|
138
|
+
if (typeof req.query['offset'] === 'string') {
|
|
139
|
+
options['offset'] = parseInt(req.query['offset'], 10);
|
|
140
|
+
}
|
|
141
|
+
if (typeof req.query['since'] === 'string' && req.query['since']) {
|
|
142
|
+
options['since'] = req.query['since'];
|
|
143
|
+
}
|
|
144
|
+
if (typeof req.query['until'] === 'string' && req.query['until']) {
|
|
145
|
+
options['until'] = req.query['until'];
|
|
146
|
+
}
|
|
147
|
+
const result = this.memorySink.query(options);
|
|
148
|
+
res.json(result);
|
|
149
|
+
});
|
|
150
|
+
// Health
|
|
151
|
+
this.app.get('/health', (_req, res) => {
|
|
152
|
+
res.json({
|
|
153
|
+
status: 'ok',
|
|
154
|
+
clients: this.clientCount,
|
|
155
|
+
uptime: Math.floor((Date.now() - this.startTime) / 1000),
|
|
156
|
+
});
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
// ---------------------------------------------------------------------------
|
|
160
|
+
// Filter matching
|
|
161
|
+
// ---------------------------------------------------------------------------
|
|
162
|
+
matchesFilter(entry, filter) {
|
|
163
|
+
if (filter.category && entry.category !== filter.category) {
|
|
164
|
+
return false;
|
|
165
|
+
}
|
|
166
|
+
if (filter.level && LOG_LEVEL_PRIORITY[entry.level] < LOG_LEVEL_PRIORITY[filter.level]) {
|
|
167
|
+
return false;
|
|
168
|
+
}
|
|
169
|
+
if (filter.source) {
|
|
170
|
+
const needle = filter.source.toLowerCase();
|
|
171
|
+
if (!entry.source.toLowerCase().includes(needle)) {
|
|
172
|
+
return false;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
if (filter.correlationId && entry.correlationId !== filter.correlationId) {
|
|
176
|
+
return false;
|
|
177
|
+
}
|
|
178
|
+
return true;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiU1NFTG9nU2luay5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9sb2dnaW5nL3NpbmtzL1NTRUxvZ1NpbmsudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7R0FVRztBQUVILE9BQU8sT0FBTyxNQUFNLFNBQVMsQ0FBQztBQUk5QixPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFFakQsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBbUJ4RCxNQUFNLE9BQU8sVUFBVTtJQUNKLEdBQUcsQ0FBNkI7SUFDekMsTUFBTSxHQUFrQixJQUFJLENBQUM7SUFDcEIsT0FBTyxHQUFHLElBQUksR0FBRyxFQUFhLENBQUM7SUFDL0IsVUFBVSxDQUFnQjtJQUMxQixJQUFJLENBQVM7SUFDYixTQUFTLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO0lBRXhDLFlBQVksT0FBMEI7UUFDcEMsSUFBSSxDQUFDLElBQUksR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDO1FBQ3pCLElBQUksQ0FBQyxVQUFVLEdBQUcsT0FBTyxDQUFDLFVBQVUsQ0FBQztRQUNyQyxJQUFJLENBQUMsR0FBRyxHQUFHLE9BQU8sRUFBRSxDQUFDO1FBQ3JCLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQztJQUNyQixDQUFDO0lBRUQsOEVBQThFO0lBQzlFLFdBQVc7SUFDWCw4RUFBOEU7SUFFOUUsS0FBSyxDQUFDLEtBQXNCO1FBQzFCLEtBQUssTUFBTSxNQUFNLElBQUksSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQ2xDLElBQUksSUFBSSxDQUFDLGFBQWEsQ0FBQyxLQUFLLEVBQUUsTUFBTSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUM7Z0JBQzdDLE1BQU0sQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLFNBQVMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUM7WUFD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Q0FBQztZQUNmLENBQUM7UUFDSCxDQUFDO1FBQ0QsSUFBSSxNQUFNLENBQUMsYUFBYSxJQUFJLEtBQUssQ0FBQyxhQUFhLEtBQUssTUFBTSxDQUFDLGFBQWEsRUFBRSxDQUFDO1lBQ3pFLE9BQU8sS0FBSyxDQUFDO1FBQ2YsQ0FBQztRQUNELE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBTU0UtYmFzZWQgcmVhbC10aW1lIGxvZyB2aWV3ZXIgc2luay5cbiAqXG4gKiBJbXBsZW1lbnRzIElMb2dTaW5rIGFuZCBydW5zIGFuIG9wdC1pbiBFeHByZXNzIEhUVFAgc2VydmVyIHRoYXQ6XG4gKiAtIFNlcnZlcyBhIGJyb3dzZXItYmFzZWQgbG9nIHZpZXdlciBhdCBHRVQgL1xuICogLSBTdHJlYW1zIGxvZyBlbnRyaWVzIHZpYSBTU0UgYXQgR0VUIC9sb2dzL3N0cmVhbVxuICogLSBFeHBvc2VzIGEgSlNPTiBxdWVyeSBlbmRwb2ludCBhdCBHRVQgL2xvZ3MgKGRlbGVnYXRlcyB0byBNZW1vcnlMb2dTaW5rKVxuICogLSBQcm92aWRlcyBhIGhlYWx0aCBlbmRwb2ludCBhdCBHRVQgL2hlYWx0aFxuICpcbiAqIFNlZSBkb2NzL0xPR0dJTkctREVTSUdOLm1kIMKnNC42IGZvciB0aGUgZnVsbCBkZXNpZ24uXG4gKi9cblxuaW1wb3J0IGV4cHJlc3MgZnJvbSAnZXhwcmVzcyc7XG5pbXBvcnQgdHlwZSB7IFJlcXVlc3QsIFJlc3BvbnNlIH0gZnJvbSAnZXhwcmVzcyc7XG5pbXBvcnQgdHlwZSB7IFNlcnZlciB9IGZyb20gJ2h0dHAnO1xuaW1wb3J0IHR5cGUgeyBJTG9nU2luaywgVW5pZmllZExvZ0VudHJ5LCBMb2dDYXRlZ29yeSwgTG9nTGV2ZWwgfSBmcm9tICcuLi90eXBlcy5qcyc7XG5pbXBvcnQgeyBMT0dfTEVWRUxfUFJJT1JJVFkgfSBmcm9tICcuLi90eXBlcy5qcyc7XG5pbXBvcnQgdHlwZSB7IE1lbW9yeUxvZ1NpbmsgfSBmcm9tICcuL01lbW9yeUxvZ1NpbmsuanMnO1xuaW1wb3J0IHsgZ2V0Vmlld2VySHRtbCB9IGZyb20gJy4uL3ZpZXdlci92aWV3ZXJIdG1sLmpzJztcblxuZXhwb3J0IGludGVyZmFjZSBTU0VMb2dTaW5rT3B0aW9ucyB7XG4gIHBvcnQ6IG51bWJlcjtcbiAgbWVtb3J5U2luazogTWVtb3J5TG9nU2luaztcbn1cblxuaW50ZXJmYWNlIFNTRUNsaWVudEZpbHRlciB7XG4gIGNhdGVnb3J5PzogTG9nQ2F0ZWdvcnk7XG4gIGxldmVsPzogTG9nTGV2ZWw7XG4gIHNvdXJjZT86IHN0cmluZztcbiAgY29ycmVsYXRpb25JZD86IHN0cmluZztcbn1cblxuaW50ZXJmYWNlIFNTRUNsaWVudCB7XG4gIHJlczogUmVzcG9uc2U7XG4gIGZpbHRlcjogU1NFQ2xpZW50RmlsdGVyO1xufVxuXG5leHBvcnQgY2xhc3MgU1NFTG9nU2luayBpbXBsZW1lbnRzIElMb2dTaW5rIHtcbiAgcHJpdmF0ZSByZWFkb25seSBhcHA6IFJldHVyblR5cGU8dHlwZW9mIGV4cHJlc3M+O1xuICBwcml2YXRlIHNlcnZlcjogU2VydmVyIHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgcmVhZG9ubHkgY2xpZW50cyA9IG5ldyBTZXQ8U1NFQ2xpZW50PigpO1xuICBwcml2YXRlIHJlYWRvbmx5IG1lbW9yeVNpbms6IE1lbW9yeUxvZ1Npbms7XG4gIHByaXZhdGUgcmVhZG9ubHkgcG9ydDogbnVtYmVyO1xuICBwcml2YXRlIHJlYWRvbmx5IHN0YXJ0VGltZSA9IERhdGUubm93KCk7XG5cbiAgY29uc3RydWN0b3Iob3B0aW9uczogU1NFTG9nU2lua09wdGlvbnMpIHtcbiAgICB0aGlzLnBvcnQgPSBvcHRpb25zLnBvcnQ7XG4gICAgdGhpcy5tZW1vcnlTaW5rID0gb3B0aW9ucy5tZW1vcnlTaW5rO1xuICAgIHRoaXMuYXBwID0gZXhwcmVzcygpO1xuICAgIHRoaXMuc2V0dXBSb3V0ZXMoKTtcbiAgfVxuXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAvLyBJTG9nU2lua1xuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuICB3cml0ZShlbnRyeTogVW5pZmllZExvZ0VudHJ5KTogdm9pZCB7XG4gICAgZm9yIChjb25zdCBjbGllbnQgb2YgdGhpcy5jbGllbnRzKSB7XG4gICAgICBpZiAodGhpcy5tYXRjaGVzRmlsdGVyKGVudHJ5LCBjbGllbnQuZmlsdGVyKSkge1xuICAgICAgICBjbGllbnQucmVzLndyaXRlKGBkYXRhOiAke0pTT04uc3RyaW5naWZ5KGVudHJ5KX1cXG5cXG5gKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBhc3luYyBmbHVzaCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAvLyBOby1vcCDigJQgU1NFIHdyaXRlcyBhcmUgaW1tZWRpYXRlLlxuICB9XG5cbiAgYXN5bmMgY2xvc2UoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgLy8gRW5kIGFsbCBjbGllbnQgY29ubmVjdGlvbnNcbiAgICBmb3IgKGNvbnN0IGNsaWVudCBvZiB0aGlzLmNsaWVudHMpIHtcbiAgICAgIGNsaWVudC5yZXMuZW5kKCk7XG4gICAgfVxuICAgIHRoaXMuY2xpZW50cy5jbGVhcigpO1xuXG4gICAgLy8gU2h1dCBkb3duIEhUVFAgc2VydmVyXG4gICAgaWYgKHRoaXMuc2VydmVyKSB7XG4gICAgICBhd2FpdCBuZXcgUHJvbWlzZTx2b2lkPigocmVzb2x2ZSkgPT4ge1xuICAgICAgICB0aGlzLnNlcnZlciEuY2xvc2UoKCkgPT4gcmVzb2x2ZSgpKTtcbiAgICAgIH0pO1xuICAgICAgdGhpcy5zZXJ2ZXIgPSBudWxsO1xuICAgIH1cbiAgfVxuXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAvLyBMaWZlY3ljbGVcbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbiAgYXN5bmMgc3RhcnQoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlPHZvaWQ+KChyZXNvbHZlKSA9PiB7XG4gICAgICB0aGlzLnNlcnZlciA9IHRoaXMuYXBwLmxpc3Rlbih0aGlzLnBvcnQsICcxMjcuMC4wLjEnLCAoKSA9PiB7XG4gICAgICAgIHRoaXMuc2VydmVyIS51bnJlZigpO1xuICAgICAgICByZXNvbHZlKCk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIGdldCBjbGllbnRDb3VudCgpOiBudW1iZXIge1xuICAgIHJldHVybiB0aGlzLmNsaWVudHMuc2l6ZTtcbiAgfVxuXG4gIGdldFBvcnQoKTogbnVtYmVyIHtcbiAgICBpZiAoIXRoaXMuc2VydmVyKSByZXR1cm4gdGhpcy5wb3J0O1xuICAgIGNvbnN0IGFkZHIgPSB0aGlzLnNlcnZlci5hZGRyZXNzKCk7XG4gICAgaWYgKGFkZHIgJiYgdHlwZW9mIGFkZHIgPT09ICdvYmplY3QnKSByZXR1cm4gYWRkci5wb3J0O1xuICAgIHJldHVybiB0aGlzLnBvcnQ7XG4gIH1cblxuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgLy8gUm91dGVzXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4gIHByaXZhdGUgc2V0dXBSb3V0ZXMoKTogdm9pZCB7XG4gICAgLy8gVmlld2VyIEhUTUxcbiAgICB0aGlzLmFwcC5nZXQoJy8nLCAoX3JlcTogUmVxdWVzdCwgcmVzOiBSZXNwb25zZSkgPT4ge1xuICAgICAgY29uc3QgYWN0dWFsUG9ydCA9IHRoaXMuZ2V0UG9ydCgpO1xuICAgICAgcmVzLnR5cGUoJ2h0bWwnKS5zZW5kKGdldFZpZXdlckh0bWwoYWN0dWFsUG9ydCkpO1xuICAgIH0pO1xuXG4gICAgLy8gU1NFIHN0cmVhbVxuICAgIHRoaXMuYXBwLmdldCgnL2xvZ3Mvc3RyZWFtJywgKHJlcTogUmVxdWVzdCwgcmVzOiBSZXNwb25zZSkgPT4ge1xuICAgICAgcmVzLndyaXRlSGVhZCgyMDAsIHtcbiAgICAgICAgJ0NvbnRlbnQtVHlwZSc6ICd0ZXh0L2V2ZW50LXN0cmVhbScsXG4gICAgICAgICdDYWNoZS1Db250cm9sJzogJ25vLWNhY2hlJyxcbiAgICAgICAgJ0Nvbm5lY3Rpb24nOiAna2VlcC1hbGl2ZScsXG4gICAgICB9KTtcbiAgICAgIHJlcy53cml0ZSgnOmNvbm5lY3RlZFxcblxcbicpO1xuXG4gICAgICBjb25zdCBmaWx0ZXI6IFNTRUNsaWVudEZpbHRlciA9IHt9O1xuICAgICAgaWYgKHR5cGVvZiByZXEucXVlcnlbJ2NhdGVnb3J5J10gPT09ICdzdHJpbmcnICYmIHJlcS5xdWVyeVsnY2F0ZWdvcnknXSkge1xuICAgICAgICBmaWx0ZXIuY2F0ZWdvcnkgPSByZXEucXVlcnlbJ2NhdGVnb3J5J10gYXMgTG9nQ2F0ZWdvcnk7XG4gICAgICB9XG4gICAgICBpZiAodHlwZW9mIHJlcS5xdWVyeVsnbGV2ZWwnXSA9PT0gJ3N0cmluZycgJiYgcmVxLnF1ZXJ5WydsZXZlbCddKSB7XG4gICAgICAgIGZpbHRlci5sZXZlbCA9IHJlcS5xdWVyeVsnbGV2ZWwnXSBhcyBMb2dMZXZlbDtcbiAgICAgIH1cbiAgICAgIGlmICh0eXBlb2YgcmVxLnF1ZXJ5Wydzb3VyY2UnXSA9PT0gJ3N0cmluZycgJiYgcmVxLnF1ZXJ5Wydzb3VyY2UnXSkge1xuICAgICAgICBmaWx0ZXIuc291cmNlID0gcmVxLnF1ZXJ5Wydzb3VyY2UnXTtcbiAgICAgIH1cbiAgICAgIGlmICh0eXBlb2YgcmVxLnF1ZXJ5Wydjb3JyZWxhdGlvbklkJ10gPT09ICdzdHJpbmcnICYmIHJlcS5xdWVyeVsnY29ycmVsYXRpb25JZCddKSB7XG4gICAgICAgIGZpbHRlci5jb3JyZWxhdGlvbklkID0gcmVxLnF1ZXJ5Wydjb3JyZWxhdGlvbklkJ107XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGNsaWVudDogU1NFQ2xpZW50ID0geyByZXMsIGZpbHRlciB9O1xuICAgICAgdGhpcy5jbGllbnRzLmFkZChjbGllbnQpO1xuXG4gICAgICAvLyBCYWNrZmlsbCByZWNlbnQgaGlzdG9yeSBzbyB0aGUgdmlld2VyIHNob3dzIGNvbnRleHQgb24gY29ubmVjdFxuICAgICAgY29uc3QgaGlzdG9yeSA9IHRoaXMubWVtb3J5U2luay5xdWVyeSh7IGNhdGVnb3J5OiAnYWxsJywgbGltaXQ6IDUwMCB9KTtcbiAgICAgIC8vIFNlbmQgb2xkZXN0LWZpcnN0IHNvIHRoZSB2aWV3ZXIgZGlzcGxheXMgaW4gY2hyb25vbG9naWNhbCBvcmRlclxuICAgICAgY29uc3QgZW50cmllcyA9IGhpc3RvcnkuZW50cmllcy5zbGljZSgpLnJldmVyc2UoKTtcbiAgICAgIGZvciAoY29uc3QgZW50cnkgb2YgZW50cmllcykge1xuICAgICAgICByZXMud3JpdGUoYGRhdGE6ICR7SlNPTi5zdHJpbmdpZnkoZW50cnkpfVxcblxcbmApO1xuICAgICAgfVxuXG4gICAgICByZXEub24oJ2Nsb3NlJywgKCkgPT4ge1xuICAgICAgICB0aGlzLmNsaWVudHMuZGVsZXRlKGNsaWVudCk7XG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIC8vIEpTT04gcXVlcnkgKGRlbGVnYXRlcyB0byBNZW1vcnlMb2dTaW5rKVxuICAgIHRoaXMuYXBwLmdldCgnL2xvZ3MnLCAocmVxOiBSZXF1ZXN0LCByZXM6IFJlc3BvbnNlKSA9PiB7XG4gICAgICBjb25zdCBvcHRpb25zOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiA9IHt9O1xuICAgICAgaWYgKHR5cGVvZiByZXEucXVlcnlbJ2NhdGVnb3J5J10gPT09ICdzdHJpbmcnICYmIHJlcS5xdWVyeVsnY2F0ZWdvcnknXSkge1xuICAgICAgICBvcHRpb25zWydjYXRlZ29yeSddID0gcmVxLnF1ZXJ5WydjYXRlZ29yeSddO1xuICAgICAgfVxuICAgICAgaWYgKHR5cGVvZiByZXEucXVlcnlbJ2xldmVsJ10gPT09ICdzdHJpbmcnICYmIHJlcS5xdWVyeVsnbGV2ZWwnXSkge1xuICAgICAgICBvcHRpb25zWydsZXZlbCddID0gcmVxLnF1ZXJ5WydsZXZlbCddO1xuICAgICAgfVxuICAgICAgaWYgKHR5cGVvZiByZXEucXVlcnlbJ3NvdXJjZSddID09PSAnc3RyaW5nJyAmJiByZXEucXVlcnlbJ3NvdXJjZSddKSB7XG4gICAgICAgIG9wdGlvbnNbJ3NvdXJjZSddID0gcmVxLnF1ZXJ5Wydzb3VyY2UnXTtcbiAgICAgIH1cbiAgICAgIGlmICh0eXBlb2YgcmVxLnF1ZXJ5WydtZXNzYWdlJ10gPT09ICdzdHJpbmcnICYmIHJlcS5xdWVyeVsnbWVzc2FnZSddKSB7XG4gICAgICAgIG9wdGlvbnNbJ21lc3NhZ2UnXSA9IHJlcS5xdWVyeVsnbWVzc2FnZSddO1xuICAgICAgfVxuICAgICAgaWYgKHR5cGVvZiByZXEucXVlcnlbJ2xpbWl0J10gPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIG9wdGlvbnNbJ2xpbWl0J10gPSBwYXJzZUludChyZXEucXVlcnlbJ2xpbWl0J10sIDEwKTtcbiAgICAgIH1cbiAgICAgIGlmICh0eXBlb2YgcmVxLnF1ZXJ5WydvZmZzZXQnXSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgb3B0aW9uc1snb2Zmc2V0J10gPSBwYXJzZUludChyZXEucXVlcnlbJ29mZnNldCddLCAxMCk7XG4gICAgICB9XG4gICAgICBpZiAodHlwZW9mIHJlcS5xdWVyeVsnc2luY2UnXSA9PT0gJ3N0cmluZycgJiYgcmVxLnF1ZXJ5WydzaW5jZSddKSB7XG4gICAgICAgIG9wdGlvbnNbJ3NpbmNlJ10gPSByZXEucXVlcnlbJ3NpbmNlJ107XG4gICAgICB9XG4gICAgICBpZiAodHlwZW9mIHJlcS5xdWVyeVsndW50aWwnXSA9PT0gJ3N0cmluZycgJiYgcmVxLnF1ZXJ5Wyd1bnRpbCddKSB7XG4gICAgICAgIG9wdGlvbnNbJ3VudGlsJ10gPSByZXEucXVlcnlbJ3VudGlsJ107XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHJlc3VsdCA9IHRoaXMubWVtb3J5U2luay5xdWVyeShvcHRpb25zKTtcbiAgICAgIHJlcy5qc29uKHJlc3VsdCk7XG4gICAgfSk7XG5cbiAgICAvLyBIZWFsdGhcbiAgICB0aGlzLmFwcC5nZXQoJy9oZWFsdGgnLCAoX3JlcTogUmVxdWVzdCwgcmVzOiBSZXNwb25zZSkgPT4ge1xuICAgICAgcmVzLmpzb24oe1xuICAgICAgICBzdGF0dXM6ICdvaycsXG4gICAgICAgIGNsaWVudHM6IHRoaXMuY2xpZW50Q291bnQsXG4gICAgICAgIHVwdGltZTogTWF0aC5mbG9vcigoRGF0ZS5ub3coKSAtIHRoaXMuc3RhcnRUaW1lKSAvIDEwMDApLFxuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgLy8gRmlsdGVyIG1hdGNoaW5nXG4gIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4gIHByaXZhdGUgbWF0Y2hlc0ZpbHRlcihlbnRyeTogVW5pZmllZExvZ0VudHJ5LCBmaWx0ZXI6IFNTRUNsaWVudEZpbHRlcik6IGJvb2xlYW4ge1xuICAgIGlmIChmaWx0ZXIuY2F0ZWdvcnkgJiYgZW50cnkuY2F0ZWdvcnkgIT09IGZpbHRlci5jYXRlZ29yeSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBpZiAoZmlsdGVyLmxldmVsICYmIExPR19MRVZFTF9QUklPUklUWVtlbnRyeS5sZXZlbF0gPCBMT0dfTEVWRUxfUFJJT1JJVFlbZmlsdGVyLmxldmVsXSkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBpZiAoZmlsdGVyLnNvdXJjZSkge1xuICAgICAgY29uc3QgbmVlZGxlID0gZmlsdGVyLnNvdXJjZS50b0xvd2VyQ2FzZSgpO1xuICAgICAgaWYgKCFlbnRyeS5zb3VyY2UudG9Mb3dlckNhc2UoKS5pbmNsdWRlcyhuZWVkbGUpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKGZpbHRlci5jb3JyZWxhdGlvbklkICYmIGVudHJ5LmNvcnJlbGF0aW9uSWQgIT09IGZpbHRlci5jb3JyZWxhdGlvbklkKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xuICB9XG59XG4iXX0=
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Embedded HTML template for the DollhouseMCP Log Viewer.
|
|
3
|
+
*
|
|
4
|
+
* Returns a self-contained vanilla JS/CSS page that connects to the
|
|
5
|
+
* SSELogSink's /logs/stream endpoint via EventSource. See docs/LOGGING-DESIGN.md §4.6.
|
|
6
|
+
*/
|
|
7
|
+
export declare function getViewerHtml(port: number): string;
|
|
8
|
+
//# sourceMappingURL=viewerHtml.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"viewerHtml.d.ts","sourceRoot":"","sources":["../../../src/logging/viewer/viewerHtml.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAoMlD"}
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Embedded HTML template for the DollhouseMCP Log Viewer.
|
|
3
|
+
*
|
|
4
|
+
* Returns a self-contained vanilla JS/CSS page that connects to the
|
|
5
|
+
* SSELogSink's /logs/stream endpoint via EventSource. See docs/LOGGING-DESIGN.md §4.6.
|
|
6
|
+
*/
|
|
7
|
+
export function getViewerHtml(port) {
|
|
8
|
+
return /* html */ `<!DOCTYPE html>
|
|
9
|
+
<html lang="en">
|
|
10
|
+
<head>
|
|
11
|
+
<meta charset="utf-8">
|
|
12
|
+
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
13
|
+
<title>DollhouseMCP Log Viewer</title>
|
|
14
|
+
<style>
|
|
15
|
+
*{box-sizing:border-box;margin:0;padding:0}
|
|
16
|
+
body{background:#1a1a2e;color:#e0e0e0;font-family:'Cascadia Code','Fira Code',monospace;font-size:13px}
|
|
17
|
+
#controls{display:flex;gap:8px;padding:8px 12px;background:#16213e;border-bottom:1px solid #0f3460;align-items:center;flex-wrap:wrap}
|
|
18
|
+
#controls label{color:#94a3b8;font-size:12px}
|
|
19
|
+
#controls select,#controls input{background:#1a1a2e;color:#e0e0e0;border:1px solid #0f3460;border-radius:4px;padding:4px 8px;font-family:inherit;font-size:12px}
|
|
20
|
+
#controls select:focus,#controls input:focus{outline:none;border-color:#e94560}
|
|
21
|
+
button{background:#0f3460;color:#e0e0e0;border:1px solid #0f3460;border-radius:4px;padding:4px 12px;cursor:pointer;font-family:inherit;font-size:12px}
|
|
22
|
+
button:hover{background:#e94560;border-color:#e94560}
|
|
23
|
+
#status{margin-left:auto;font-size:11px;padding:2px 8px;border-radius:10px}
|
|
24
|
+
.connected{background:#064e3b;color:#6ee7b7}
|
|
25
|
+
.disconnected{background:#7f1d1d;color:#fca5a5}
|
|
26
|
+
.paused{background:#78350f;color:#fcd34d}
|
|
27
|
+
#log{overflow-y:auto;height:calc(100vh - 44px);padding:8px 12px}
|
|
28
|
+
.entry{padding:2px 0;white-space:pre-wrap;word-break:break-word;border-bottom:1px solid #1e293b}
|
|
29
|
+
.entry:hover{background:#16213e}
|
|
30
|
+
.lvl-error{color:#f87171}
|
|
31
|
+
.lvl-warn{color:#fbbf24}
|
|
32
|
+
.lvl-info{color:#60a5fa}
|
|
33
|
+
.lvl-debug{color:#9ca3af}
|
|
34
|
+
.ts{color:#64748b}
|
|
35
|
+
.cat{color:#a78bfa}
|
|
36
|
+
.src{color:#2dd4bf}
|
|
37
|
+
.cid{color:#f472b6;font-size:11px;display:inline-block;width:72px;text-align:right;margin-right:4px}
|
|
38
|
+
#search{margin-left:4px}
|
|
39
|
+
</style>
|
|
40
|
+
</head>
|
|
41
|
+
<body>
|
|
42
|
+
<div id="controls">
|
|
43
|
+
<label>Category
|
|
44
|
+
<select id="fCategory">
|
|
45
|
+
<option value="">all</option>
|
|
46
|
+
<option value="application">application</option>
|
|
47
|
+
<option value="security">security</option>
|
|
48
|
+
<option value="performance">performance</option>
|
|
49
|
+
<option value="telemetry">telemetry</option>
|
|
50
|
+
</select>
|
|
51
|
+
</label>
|
|
52
|
+
<label>Level
|
|
53
|
+
<select id="fLevel">
|
|
54
|
+
<option value="">all</option>
|
|
55
|
+
<option value="debug">debug</option>
|
|
56
|
+
<option value="info">info</option>
|
|
57
|
+
<option value="warn">warn</option>
|
|
58
|
+
<option value="error">error</option>
|
|
59
|
+
</select>
|
|
60
|
+
</label>
|
|
61
|
+
<label>Source <input id="fSource" placeholder="substring" size="14"></label>
|
|
62
|
+
<label>RequestId <input id="fCorrelationId" placeholder="correlationId" size="20"></label>
|
|
63
|
+
<label>Search <input id="search" placeholder="message filter" size="18"></label>
|
|
64
|
+
<button id="btnPause">Pause</button>
|
|
65
|
+
<button id="btnClear">Clear</button>
|
|
66
|
+
<span id="status" class="disconnected">disconnected</span>
|
|
67
|
+
</div>
|
|
68
|
+
<div id="log"></div>
|
|
69
|
+
<script>
|
|
70
|
+
(function(){
|
|
71
|
+
var BASE = 'http://127.0.0.1:${port}';
|
|
72
|
+
var MAX_ENTRIES = 1000;
|
|
73
|
+
var log = document.getElementById('log');
|
|
74
|
+
var status = document.getElementById('status');
|
|
75
|
+
var fCategory = document.getElementById('fCategory');
|
|
76
|
+
var fLevel = document.getElementById('fLevel');
|
|
77
|
+
var fSource = document.getElementById('fSource');
|
|
78
|
+
var fCorrelationId = document.getElementById('fCorrelationId');
|
|
79
|
+
var searchBox = document.getElementById('search');
|
|
80
|
+
var btnPause = document.getElementById('btnPause');
|
|
81
|
+
var btnClear = document.getElementById('btnClear');
|
|
82
|
+
var es = null;
|
|
83
|
+
var paused = false;
|
|
84
|
+
var buffer = [];
|
|
85
|
+
|
|
86
|
+
function escHtml(s){
|
|
87
|
+
var d = document.createElement('div');
|
|
88
|
+
d.appendChild(document.createTextNode(s));
|
|
89
|
+
return d.innerHTML;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function setStatus(s, cls){
|
|
93
|
+
status.textContent = s;
|
|
94
|
+
status.className = cls;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
var LEVEL_ORDER = {debug:0, info:1, warn:2, error:3};
|
|
100
|
+
|
|
101
|
+
function matchesFilters(entry){
|
|
102
|
+
var cat = fCategory.value;
|
|
103
|
+
if(cat && entry.category !== cat) return false;
|
|
104
|
+
var lvl = fLevel.value;
|
|
105
|
+
if(lvl && (LEVEL_ORDER[entry.level]||0) < (LEVEL_ORDER[lvl]||0)) return false;
|
|
106
|
+
var src = fSource.value.toLowerCase();
|
|
107
|
+
if(src && (!entry.source || entry.source.toLowerCase().indexOf(src) === -1)) return false;
|
|
108
|
+
var cid = fCorrelationId.value;
|
|
109
|
+
if(cid && entry.correlationId !== cid) return false;
|
|
110
|
+
var needle = searchBox.value.toLowerCase();
|
|
111
|
+
if(needle && (!entry.message || entry.message.toLowerCase().indexOf(needle) === -1)) return false;
|
|
112
|
+
return true;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function refilter(){
|
|
116
|
+
var els = log.children;
|
|
117
|
+
for(var i = 0; i < els.length; i++){
|
|
118
|
+
var data = els[i]._entryData;
|
|
119
|
+
if(data){
|
|
120
|
+
els[i].style.display = matchesFilters(data) ? '' : 'none';
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function addEntry(entry){
|
|
126
|
+
if(!matchesFilters(entry)) var hidden = true;
|
|
127
|
+
|
|
128
|
+
var el = document.createElement('div');
|
|
129
|
+
el.className = 'entry lvl-' + entry.level;
|
|
130
|
+
el._entryData = entry;
|
|
131
|
+
if(hidden) el.style.display = 'none';
|
|
132
|
+
var ts = entry.timestamp ? entry.timestamp.slice(11, 23) : '';
|
|
133
|
+
var cid = entry.correlationId ? entry.correlationId.slice(-8) : '';
|
|
134
|
+
el.innerHTML = '<span class="ts">' + escHtml(ts) + '</span> '
|
|
135
|
+
+ '<span class="cid">' + escHtml(cid) + '</span> '
|
|
136
|
+
+ '<span class="cat">[' + escHtml(entry.category) + ']</span> '
|
|
137
|
+
+ '<span class="src">' + escHtml(entry.source) + '</span> '
|
|
138
|
+
+ escHtml(entry.message);
|
|
139
|
+
log.appendChild(el);
|
|
140
|
+
|
|
141
|
+
while(log.children.length > MAX_ENTRIES){
|
|
142
|
+
log.removeChild(log.firstChild);
|
|
143
|
+
}
|
|
144
|
+
if(!hidden) log.scrollTop = log.scrollHeight;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function connect(){
|
|
148
|
+
if(es){ es.close(); }
|
|
149
|
+
es = new EventSource(BASE + '/logs/stream');
|
|
150
|
+
es.onopen = function(){ setStatus('connected', 'connected'); };
|
|
151
|
+
es.onmessage = function(e){
|
|
152
|
+
try{
|
|
153
|
+
var entry = JSON.parse(e.data);
|
|
154
|
+
if(paused){ buffer.push(entry); }
|
|
155
|
+
else { addEntry(entry); }
|
|
156
|
+
}catch(err){}
|
|
157
|
+
};
|
|
158
|
+
es.onerror = function(){ setStatus('disconnected', 'disconnected'); };
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
var filterTimer = null;
|
|
162
|
+
function onFilterChange(){
|
|
163
|
+
clearTimeout(filterTimer);
|
|
164
|
+
filterTimer = setTimeout(refilter, 50);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
fCategory.addEventListener('change', onFilterChange);
|
|
168
|
+
fLevel.addEventListener('change', onFilterChange);
|
|
169
|
+
fSource.addEventListener('input', function(){
|
|
170
|
+
clearTimeout(filterTimer);
|
|
171
|
+
filterTimer = setTimeout(refilter, 400);
|
|
172
|
+
});
|
|
173
|
+
fCorrelationId.addEventListener('input', function(){
|
|
174
|
+
clearTimeout(filterTimer);
|
|
175
|
+
filterTimer = setTimeout(refilter, 400);
|
|
176
|
+
});
|
|
177
|
+
searchBox.addEventListener('input', function(){
|
|
178
|
+
clearTimeout(filterTimer);
|
|
179
|
+
filterTimer = setTimeout(refilter, 400);
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
btnPause.addEventListener('click', function(){
|
|
183
|
+
paused = !paused;
|
|
184
|
+
btnPause.textContent = paused ? 'Resume' : 'Pause';
|
|
185
|
+
if(paused){
|
|
186
|
+
setStatus('paused', 'paused');
|
|
187
|
+
} else {
|
|
188
|
+
setStatus('connected', 'connected');
|
|
189
|
+
buffer.forEach(addEntry);
|
|
190
|
+
buffer = [];
|
|
191
|
+
}
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
btnClear.addEventListener('click', function(){
|
|
195
|
+
log.innerHTML = '';
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
connect();
|
|
199
|
+
})();
|
|
200
|
+
</script>
|
|
201
|
+
</body>
|
|
202
|
+
</html>`;
|
|
203
|
+
}
|
|
204
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmlld2VySHRtbC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9sb2dnaW5nL3ZpZXdlci92aWV3ZXJIdG1sLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7OztHQUtHO0FBRUgsTUFBTSxVQUFVLGFBQWEsQ0FBQyxJQUFZO0lBQ3hDLE9BQU8sVUFBVSxDQUFDOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7aUNBK0RhLElBQUk7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O1FBbUk3QixDQUFDO0FBQ1QsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogRW1iZWRkZWQgSFRNTCB0ZW1wbGF0ZSBmb3IgdGhlIERvbGxob3VzZU1DUCBMb2cgVmlld2VyLlxuICpcbiAqIFJldHVybnMgYSBzZWxmLWNvbnRhaW5lZCB2YW5pbGxhIEpTL0NTUyBwYWdlIHRoYXQgY29ubmVjdHMgdG8gdGhlXG4gKiBTU0VMb2dTaW5rJ3MgL2xvZ3Mvc3RyZWFtIGVuZHBvaW50IHZpYSBFdmVudFNvdXJjZS4gU2VlIGRvY3MvTE9HR0lORy1ERVNJR04ubWQgwqc0LjYuXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGdldFZpZXdlckh0bWwocG9ydDogbnVtYmVyKTogc3RyaW5nIHtcbiAgcmV0dXJuIC8qIGh0bWwgKi8gYDwhRE9DVFlQRSBodG1sPlxuPGh0bWwgbGFuZz1cImVuXCI+XG48aGVhZD5cbjxtZXRhIGNoYXJzZXQ9XCJ1dGYtOFwiPlxuPG1ldGEgbmFtZT1cInZpZXdwb3J0XCIgY29udGVudD1cIndpZHRoPWRldmljZS13aWR0aCxpbml0aWFsLXNjYWxlPTFcIj5cbjx0aXRsZT5Eb2xsaG91c2VNQ1AgTG9nIFZpZXdlcjwvdGl0bGU+XG48c3R5bGU+XG4qe2JveC1zaXppbmc6Ym9yZGVyLWJveDttYXJnaW46MDtwYWRkaW5nOjB9XG5ib2R5e2JhY2tncm91bmQ6IzFhMWEyZTtjb2xvcjojZTBlMGUwO2ZvbnQtZmFtaWx5OidDYXNjYWRpYSBDb2RlJywnRmlyYSBDb2RlJyxtb25vc3BhY2U7Zm9udC1zaXplOjEzcHh9XG4jY29udHJvbHN7ZGlzcGxheTpmbGV4O2dhcDo4cHg7cGFkZGluZzo4cHggMTJweDtiYWNrZ3JvdW5kOiMxNjIxM2U7Ym9yZGVyLWJvdHRvbToxcHggc29saWQgIzBmMzQ2MDthbGlnbi1pdGVtczpjZW50ZXI7ZmxleC13cmFwOndyYXB9XG4jY29udHJvbHMgbGFiZWx7Y29sb3I6Izk0YTNiODtmb250LXNpemU6MTJweH1cbiNjb250cm9scyBzZWxlY3QsI2NvbnRyb2xzIGlucHV0e2JhY2tncm91bmQ6IzFhMWEyZTtjb2xvcjojZTBlMGUwO2JvcmRlcjoxcHggc29saWQgIzBmMzQ2MDtib3JkZXItcmFkaXVzOjRweDtwYWRkaW5nOjRweCA4cHg7Zm9udC1mYW1pbHk6aW5oZXJpdDtmb250LXNpemU6MTJweH1cbiNjb250cm9scyBzZWxlY3Q6Zm9jdXMsI2NvbnRyb2xzIGlucHV0OmZvY3Vze291dGxpbmU6bm9uZTtib3JkZXItY29sb3I6I2U5NDU2MH1cbmJ1dHRvbntiYWNrZ3JvdW5kOiMwZjM0NjA7Y29sb3I6I2UwZTBlMDtib3JkZXI6MXB4IHNvbGlkICMwZjM0NjA7Ym9yZGVyLXJhZGl1czo0cHg7cGFkZGluZzo0cHggMTJweDtjdXJzb3I6cG9pbnRlcjtmb250LWZhbWlseTppbmhlcml0O2ZvbnQtc2l6ZToxMnB4fVxuYnV0dG9uOmhvdmVye2JhY2tncm91bmQ6I2U5NDU2MDtib3JkZXItY29sb3I6I2U5NDU2MH1cbiNzdGF0dXN7bWFyZ2luLWxlZnQ6YXV0bztmb250LXNpemU6MTFweDtwYWRkaW5nOjJweCA4cHg7Ym9yZGVyLXJhZGl1czoxMHB4fVxuLmNvbm5lY3RlZHtiYWNrZ3JvdW5kOiMwNjRlM2I7Y29sb3I6IzZlZTdiN31cbi5kaXNjb25uZWN0ZWR7YmFja2dyb3VuZDojN2YxZDFkO2NvbG9yOiNmY2E1YTV9XG4ucGF1c2Vke2JhY2tncm91bmQ6Izc4MzUwZjtjb2xvcjojZmNkMzRkfVxuI2xvZ3tvdmVyZmxvdy15OmF1dG87aGVpZ2h0OmNhbGMoMTAwdmggLSA0NHB4KTtwYWRkaW5nOjhweCAxMnB4fVxuLmVudHJ5e3BhZGRpbmc6MnB4IDA7d2hpdGUtc3BhY2U6cHJlLXdyYXA7d29yZC1icmVhazpicmVhay13b3JkO2JvcmRlci1ib3R0b206MXB4IHNvbGlkICMxZTI5M2J9XG4uZW50cnk6aG92ZXJ7YmFja2dyb3VuZDojMTYyMTNlfVxuLmx2bC1lcnJvcntjb2xvcjojZjg3MTcxfVxuLmx2bC13YXJue2NvbG9yOiNmYmJmMjR9XG4ubHZsLWluZm97Y29sb3I6IzYwYTVmYX1cbi5sdmwtZGVidWd7Y29sb3I6IzljYTNhZn1cbi50c3tjb2xvcjojNjQ3NDhifVxuLmNhdHtjb2xvcjojYTc4YmZhfVxuLnNyY3tjb2xvcjojMmRkNGJmfVxuLmNpZHtjb2xvcjojZjQ3MmI2O2ZvbnQtc2l6ZToxMXB4O2Rpc3BsYXk6aW5saW5lLWJsb2NrO3dpZHRoOjcycHg7dGV4dC1hbGlnbjpyaWdodDttYXJnaW4tcmlnaHQ6NHB4fVxuI3NlYXJjaHttYXJnaW4tbGVmdDo0cHh9XG48L3N0eWxlPlxuPC9oZWFkPlxuPGJvZHk+XG48ZGl2IGlkPVwiY29udHJvbHNcIj5cbiAgPGxhYmVsPkNhdGVnb3J5XG4gICAgPHNlbGVjdCBpZD1cImZDYXRlZ29yeVwiPlxuICAgICAgPG9wdGlvbiB2YWx1ZT1cIlwiPmFsbDwvb3B0aW9uPlxuICAgICAgPG9wdGlvbiB2YWx1ZT1cImFwcGxpY2F0aW9uXCI+YXBwbGljYXRpb248L29wdGlvbj5cbiAgICAgIDxvcHRpb24gdmFsdWU9XCJzZWN1cml0eVwiPnNlY3VyaXR5PC9vcHRpb24+XG4gICAgICA8b3B0aW9uIHZhbHVlPVwicGVyZm9ybWFuY2VcIj5wZXJmb3JtYW5jZTwvb3B0aW9uPlxuICAgICAgPG9wdGlvbiB2YWx1ZT1cInRlbGVtZXRyeVwiPnRlbGVtZXRyeTwvb3B0aW9uPlxuICAgIDwvc2VsZWN0PlxuICA8L2xhYmVsPlxuICA8bGFiZWw+TGV2ZWxcbiAgICA8c2VsZWN0IGlkPVwiZkxldmVsXCI+XG4gICAgICA8b3B0aW9uIHZhbHVlPVwiXCI+YWxsPC9vcHRpb24+XG4gICAgICA8b3B0aW9uIHZhbHVlPVwiZGVidWdcIj5kZWJ1Zzwvb3B0aW9uPlxuICAgICAgPG9wdGlvbiB2YWx1ZT1cImluZm9cIj5pbmZvPC9vcHRpb24+XG4gICAgICA8b3B0aW9uIHZhbHVlPVwid2FyblwiPndhcm48L29wdGlvbj5cbiAgICAgIDxvcHRpb24gdmFsdWU9XCJlcnJvclwiPmVycm9yPC9vcHRpb24+XG4gICAgPC9zZWxlY3Q+XG4gIDwvbGFiZWw+XG4gIDxsYWJlbD5Tb3VyY2UgPGlucHV0IGlkPVwiZlNvdXJjZVwiIHBsYWNlaG9sZGVyPVwic3Vic3RyaW5nXCIgc2l6ZT1cIjE0XCI+PC9sYWJlbD5cbiAgPGxhYmVsPlJlcXVlc3RJZCA8aW5wdXQgaWQ9XCJmQ29ycmVsYXRpb25JZFwiIHBsYWNlaG9sZGVyPVwiY29ycmVsYXRpb25JZFwiIHNpemU9XCIyMFwiPjwvbGFiZWw+XG4gIDxsYWJlbD5TZWFyY2ggPGlucHV0IGlkPVwic2VhcmNoXCIgcGxhY2Vob2xkZXI9XCJtZXNzYWdlIGZpbHRlclwiIHNpemU9XCIxOFwiPjwvbGFiZWw+XG4gIDxidXR0b24gaWQ9XCJidG5QYXVzZVwiPlBhdXNlPC9idXR0b24+XG4gIDxidXR0b24gaWQ9XCJidG5DbGVhclwiPkNsZWFyPC9idXR0b24+XG4gIDxzcGFuIGlkPVwic3RhdHVzXCIgY2xhc3M9XCJkaXNjb25uZWN0ZWRcIj5kaXNjb25uZWN0ZWQ8L3NwYW4+XG48L2Rpdj5cbjxkaXYgaWQ9XCJsb2dcIj48L2Rpdj5cbjxzY3JpcHQ+XG4oZnVuY3Rpb24oKXtcbiAgdmFyIEJBU0UgPSAnaHR0cDovLzEyNy4wLjAuMToke3BvcnR9JztcbiAgdmFyIE1BWF9FTlRSSUVTID0gMTAwMDtcbiAgdmFyIGxvZyA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdsb2cnKTtcbiAgdmFyIHN0YXR1cyA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdzdGF0dXMnKTtcbiAgdmFyIGZDYXRlZ29yeSA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdmQ2F0ZWdvcnknKTtcbiAgdmFyIGZMZXZlbCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdmTGV2ZWwnKTtcbiAgdmFyIGZTb3VyY2UgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnZlNvdXJjZScpO1xuICB2YXIgZkNvcnJlbGF0aW9uSWQgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnZkNvcnJlbGF0aW9uSWQnKTtcbiAgdmFyIHNlYXJjaEJveCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdzZWFyY2gnKTtcbiAgdmFyIGJ0blBhdXNlID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2J0blBhdXNlJyk7XG4gIHZhciBidG5DbGVhciA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdidG5DbGVhcicpO1xuICB2YXIgZXMgPSBudWxsO1xuICB2YXIgcGF1c2VkID0gZmFsc2U7XG4gIHZhciBidWZmZXIgPSBbXTtcblxuICBmdW5jdGlvbiBlc2NIdG1sKHMpe1xuICAgIHZhciBkID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgZC5hcHBlbmRDaGlsZChkb2N1bWVudC5jcmVhdGVUZXh0Tm9kZShzKSk7XG4gICAgcmV0dXJuIGQuaW5uZXJIVE1MO1xuICB9XG5cbiAgZnVuY3Rpb24gc2V0U3RhdHVzKHMsIGNscyl7XG4gICAgc3RhdHVzLnRleHRDb250ZW50ID0gcztcbiAgICBzdGF0dXMuY2xhc3NOYW1lID0gY2xzO1xuICB9XG5cblxuXG4gIHZhciBMRVZFTF9PUkRFUiA9IHtkZWJ1ZzowLCBpbmZvOjEsIHdhcm46MiwgZXJyb3I6M307XG5cbiAgZnVuY3Rpb24gbWF0Y2hlc0ZpbHRlcnMoZW50cnkpe1xuICAgIHZhciBjYXQgPSBmQ2F0ZWdvcnkudmFsdWU7XG4gICAgaWYoY2F0ICYmIGVudHJ5LmNhdGVnb3J5ICE9PSBjYXQpIHJldHVybiBmYWxzZTtcbiAgICB2YXIgbHZsID0gZkxldmVsLnZhbHVlO1xuICAgIGlmKGx2bCAmJiAoTEVWRUxfT1JERVJbZW50cnkubGV2ZWxdfHwwKSA8IChMRVZFTF9PUkRFUltsdmxdfHwwKSkgcmV0dXJuIGZhbHNlO1xuICAgIHZhciBzcmMgPSBmU291cmNlLnZhbHVlLnRvTG93ZXJDYXNlKCk7XG4gICAgaWYoc3JjICYmICghZW50cnkuc291cmNlIHx8IGVudHJ5LnNvdXJjZS50b0xvd2VyQ2FzZSgpLmluZGV4T2Yoc3JjKSA9PT0gLTEpKSByZXR1cm4gZmFsc2U7XG4gICAgdmFyIGNpZCA9IGZDb3JyZWxhdGlvbklkLnZhbHVlO1xuICAgIGlmKGNpZCAmJiBlbnRyeS5jb3JyZWxhdGlvbklkICE9PSBjaWQpIHJldHVybiBmYWxzZTtcbiAgICB2YXIgbmVlZGxlID0gc2VhcmNoQm94LnZhbHVlLnRvTG93ZXJDYXNlKCk7XG4gICAgaWYobmVlZGxlICYmICghZW50cnkubWVzc2FnZSB8fCBlbnRyeS5tZXNzYWdlLnRvTG93ZXJDYXNlKCkuaW5kZXhPZihuZWVkbGUpID09PSAtMSkpIHJldHVybiBmYWxzZTtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHJlZmlsdGVyKCl7XG4gICAgdmFyIGVscyA9IGxvZy5jaGlsZHJlbjtcbiAgICBmb3IodmFyIGkgPSAwOyBpIDwgZWxzLmxlbmd0aDsgaSsrKXtcbiAgICAgIHZhciBkYXRhID0gZWxzW2ldLl9lbnRyeURhdGE7XG4gICAgICBpZihkYXRhKXtcbiAgICAgICAgZWxzW2ldLnN0eWxlLmRpc3BsYXkgPSBtYXRjaGVzRmlsdGVycyhkYXRhKSA/ICcnIDogJ25vbmUnO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIGFkZEVudHJ5KGVudHJ5KXtcbiAgICBpZighbWF0Y2hlc0ZpbHRlcnMoZW50cnkpKSB2YXIgaGlkZGVuID0gdHJ1ZTtcblxuICAgIHZhciBlbCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpO1xuICAgIGVsLmNsYXNzTmFtZSA9ICdlbnRyeSBsdmwtJyArIGVudHJ5LmxldmVsO1xuICAgIGVsLl9lbnRyeURhdGEgPSBlbnRyeTtcbiAgICBpZihoaWRkZW4pIGVsLnN0eWxlLmRpc3BsYXkgPSAnbm9uZSc7XG4gICAgdmFyIHRzID0gZW50cnkudGltZXN0YW1wID8gZW50cnkudGltZXN0YW1wLnNsaWNlKDExLCAyMykgOiAnJztcbiAgICB2YXIgY2lkID0gZW50cnkuY29ycmVsYXRpb25JZCA/IGVudHJ5LmNvcnJlbGF0aW9uSWQuc2xpY2UoLTgpIDogJyc7XG4gICAgZWwuaW5uZXJIVE1MID0gJzxzcGFuIGNsYXNzPVwidHNcIj4nICsgZXNjSHRtbCh0cykgKyAnPC9zcGFuPiAnXG4gICAgICArICc8c3BhbiBjbGFzcz1cImNpZFwiPicgKyBlc2NIdG1sKGNpZCkgKyAnPC9zcGFuPiAnXG4gICAgICArICc8c3BhbiBjbGFzcz1cImNhdFwiPlsnICsgZXNjSHRtbChlbnRyeS5jYXRlZ29yeSkgKyAnXTwvc3Bhbj4gJ1xuICAgICAgKyAnPHNwYW4gY2xhc3M9XCJzcmNcIj4nICsgZXNjSHRtbChlbnRyeS5zb3VyY2UpICsgJzwvc3Bhbj4gJ1xuICAgICAgKyBlc2NIdG1sKGVudHJ5Lm1lc3NhZ2UpO1xuICAgIGxvZy5hcHBlbmRDaGlsZChlbCk7XG5cbiAgICB3aGlsZShsb2cuY2hpbGRyZW4ubGVuZ3RoID4gTUFYX0VOVFJJRVMpe1xuICAgICAgbG9nLnJlbW92ZUNoaWxkKGxvZy5maXJzdENoaWxkKTtcbiAgICB9XG4gICAgaWYoIWhpZGRlbikgbG9nLnNjcm9sbFRvcCA9IGxvZy5zY3JvbGxIZWlnaHQ7XG4gIH1cblxuICBmdW5jdGlvbiBjb25uZWN0KCl7XG4gICAgaWYoZXMpeyBlcy5jbG9zZSgpOyB9XG4gICAgZXMgPSBuZXcgRXZlbnRTb3VyY2UoQkFTRSArICcvbG9ncy9zdHJlYW0nKTtcbiAgICBlcy5vbm9wZW4gPSBmdW5jdGlvbigpeyBzZXRTdGF0dXMoJ2Nvbm5lY3RlZCcsICdjb25uZWN0ZWQnKTsgfTtcbiAgICBlcy5vbm1lc3NhZ2UgPSBmdW5jdGlvbihlKXtcbiAgICAgIHRyeXtcbiAgICAgICAgdmFyIGVudHJ5ID0gSlNPTi5wYXJzZShlLmRhdGEpO1xuICAgICAgICBpZihwYXVzZWQpeyBidWZmZXIucHVzaChlbnRyeSk7IH1cbiAgICAgICAgZWxzZSB7IGFkZEVudHJ5KGVudHJ5KTsgfVxuICAgICAgfWNhdGNoKGVycil7fVxuICAgIH07XG4gICAgZXMub25lcnJvciA9IGZ1bmN0aW9uKCl7IHNldFN0YXR1cygnZGlzY29ubmVjdGVkJywgJ2Rpc2Nvbm5lY3RlZCcpOyB9O1xuICB9XG5cbiAgdmFyIGZpbHRlclRpbWVyID0gbnVsbDtcbiAgZnVuY3Rpb24gb25GaWx0ZXJDaGFuZ2UoKXtcbiAgICBjbGVhclRpbWVvdXQoZmlsdGVyVGltZXIpO1xuICAgIGZpbHRlclRpbWVyID0gc2V0VGltZW91dChyZWZpbHRlciwgNTApO1xuICB9XG5cbiAgZkNhdGVnb3J5LmFkZEV2ZW50TGlzdGVuZXIoJ2NoYW5nZScsIG9uRmlsdGVyQ2hhbmdlKTtcbiAgZkxldmVsLmFkZEV2ZW50TGlzdGVuZXIoJ2NoYW5nZScsIG9uRmlsdGVyQ2hhbmdlKTtcbiAgZlNvdXJjZS5hZGRFdmVudExpc3RlbmVyKCdpbnB1dCcsIGZ1bmN0aW9uKCl7XG4gICAgY2xlYXJUaW1lb3V0KGZpbHRlclRpbWVyKTtcbiAgICBmaWx0ZXJUaW1lciA9IHNldFRpbWVvdXQocmVmaWx0ZXIsIDQwMCk7XG4gIH0pO1xuICBmQ29ycmVsYXRpb25JZC5hZGRFdmVudExpc3RlbmVyKCdpbnB1dCcsIGZ1bmN0aW9uKCl7XG4gICAgY2xlYXJUaW1lb3V0KGZpbHRlclRpbWVyKTtcbiAgICBmaWx0ZXJUaW1lciA9IHNldFRpbWVvdXQocmVmaWx0ZXIsIDQwMCk7XG4gIH0pO1xuICBzZWFyY2hCb3guYWRkRXZlbnRMaXN0ZW5lcignaW5wdXQnLCBmdW5jdGlvbigpe1xuICAgIGNsZWFyVGltZW91dChmaWx0ZXJUaW1lcik7XG4gICAgZmlsdGVyVGltZXIgPSBzZXRUaW1lb3V0KHJlZmlsdGVyLCA0MDApO1xuICB9KTtcblxuICBidG5QYXVzZS5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIGZ1bmN0aW9uKCl7XG4gICAgcGF1c2VkID0gIXBhdXNlZDtcbiAgICBidG5QYXVzZS50ZXh0Q29udGVudCA9IHBhdXNlZCA/ICdSZXN1bWUnIDogJ1BhdXNlJztcbiAgICBpZihwYXVzZWQpe1xuICAgICAgc2V0U3RhdHVzKCdwYXVzZWQnLCAncGF1c2VkJyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHNldFN0YXR1cygnY29ubmVjdGVkJywgJ2Nvbm5lY3RlZCcpO1xuICAgICAgYnVmZmVyLmZvckVhY2goYWRkRW50cnkpO1xuICAgICAgYnVmZmVyID0gW107XG4gICAgfVxuICB9KTtcblxuICBidG5DbGVhci5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIGZ1bmN0aW9uKCl7XG4gICAgbG9nLmlubmVySFRNTCA9ICcnO1xuICB9KTtcblxuICBjb25uZWN0KCk7XG59KSgpO1xuPC9zY3JpcHQ+XG48L2JvZHk+XG48L2h0bWw+YDtcbn1cbiJdfQ==
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dollhousemcp/mcp-server",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.1",
|
|
4
4
|
"description": "DollhouseMCP - A Model Context Protocol (MCP) server that enables dynamic AI persona management from markdown files, allowing Claude and other compatible AI assistants to activate and switch between different behavioral personas.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
package/server.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"name": "io.github.DollhouseMCP/mcp-server",
|
|
4
4
|
"title": "DollhouseMCP",
|
|
5
5
|
"description": "OSS to create Personas, Skills, Templates, Agents, and Memories to customize your AI experience.",
|
|
6
|
-
"version": "2.0.
|
|
6
|
+
"version": "2.0.1",
|
|
7
7
|
"homepage": "https://dollhousemcp.com",
|
|
8
8
|
"repository": {
|
|
9
9
|
"type": "git",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
{
|
|
30
30
|
"registryType": "npm",
|
|
31
31
|
"identifier": "@dollhousemcp/mcp-server",
|
|
32
|
-
"version": "2.0.
|
|
32
|
+
"version": "2.0.1",
|
|
33
33
|
"transport": {
|
|
34
34
|
"type": "stdio"
|
|
35
35
|
}
|