@jagilber-org/index-server 1.26.5 → 1.26.11
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/CHANGELOG.md +142 -110
- package/dist/dashboard/client/admin.html +26 -26
- package/dist/lib/mcpStdioLogging.d.ts +12 -0
- package/dist/lib/mcpStdioLogging.js +39 -0
- package/dist/services/logger.js +28 -13
- package/package.json +2 -1
- package/scripts/setup-wizard.mjs +268 -16
- package/server.json +2 -2
|
@@ -1,29 +1,29 @@
|
|
|
1
1
|
<!DOCTYPE html>
|
|
2
2
|
<html lang="en">
|
|
3
3
|
<head>
|
|
4
|
-
<meta name="dashboard-build-version" content="1.26.
|
|
4
|
+
<meta name="dashboard-build-version" content="1.26.11-9badd8dd">
|
|
5
5
|
<meta charset="UTF-8">
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
7
7
|
<title>Index Server Admin</title>
|
|
8
|
-
<link rel="stylesheet" href="css/admin.css?v=1.26.
|
|
9
|
-
<script defer src="js/admin.utils.js?v=1.26.
|
|
10
|
-
<script defer src="js/admin.auth.js?v=1.26.
|
|
11
|
-
<script defer src="js/admin.overview.js?v=1.26.
|
|
12
|
-
<script defer src="js/admin.sessions.js?v=1.26.
|
|
13
|
-
<script defer src="js/admin.monitor.js?v=1.26.
|
|
14
|
-
<script defer src="js/admin.graph.js?v=1.26.
|
|
8
|
+
<link rel="stylesheet" href="css/admin.css?v=1.26.11-9badd8dd">
|
|
9
|
+
<script defer src="js/admin.utils.js?v=1.26.11-9badd8dd"></script>
|
|
10
|
+
<script defer src="js/admin.auth.js?v=1.26.11-9badd8dd"></script>
|
|
11
|
+
<script defer src="js/admin.overview.js?v=1.26.11-9badd8dd"></script>
|
|
12
|
+
<script defer src="js/admin.sessions.js?v=1.26.11-9badd8dd"></script>
|
|
13
|
+
<script defer src="js/admin.monitor.js?v=1.26.11-9badd8dd"></script>
|
|
14
|
+
<script defer src="js/admin.graph.js?v=1.26.11-9badd8dd"></script>
|
|
15
15
|
<script defer src="js/marked.umd.js"></script>
|
|
16
|
-
<script defer src="js/admin.instructions.js?v=1.26.
|
|
17
|
-
<script defer src="js/admin.logs.js?v=1.26.
|
|
18
|
-
<script defer src="js/admin.maintenance.js?v=1.26.
|
|
19
|
-
<script defer src="js/admin.config.js?v=1.26.
|
|
20
|
-
<script defer src="js/admin.performance.js?v=1.26.
|
|
21
|
-
<script defer src="js/admin.instances.js?v=1.26.
|
|
22
|
-
<script defer src="js/admin.embeddings.js?v=1.26.
|
|
23
|
-
<script defer src="js/admin.messaging.js?v=1.26.
|
|
24
|
-
<script defer src="js/admin.sqlite.js?v=1.26.
|
|
25
|
-
<script defer src="js/admin.boot.js?v=1.26.
|
|
26
|
-
<script defer src="js/admin.feedback.js?v=1.26.
|
|
16
|
+
<script defer src="js/admin.instructions.js?v=1.26.11-9badd8dd"></script>
|
|
17
|
+
<script defer src="js/admin.logs.js?v=1.26.11-9badd8dd"></script>
|
|
18
|
+
<script defer src="js/admin.maintenance.js?v=1.26.11-9badd8dd"></script>
|
|
19
|
+
<script defer src="js/admin.config.js?v=1.26.11-9badd8dd"></script>
|
|
20
|
+
<script defer src="js/admin.performance.js?v=1.26.11-9badd8dd"></script>
|
|
21
|
+
<script defer src="js/admin.instances.js?v=1.26.11-9badd8dd"></script>
|
|
22
|
+
<script defer src="js/admin.embeddings.js?v=1.26.11-9badd8dd"></script>
|
|
23
|
+
<script defer src="js/admin.messaging.js?v=1.26.11-9badd8dd"></script>
|
|
24
|
+
<script defer src="js/admin.sqlite.js?v=1.26.11-9badd8dd"></script>
|
|
25
|
+
<script defer src="js/admin.boot.js?v=1.26.11-9badd8dd"></script>
|
|
26
|
+
<script defer src="js/admin.feedback.js?v=1.26.11-9badd8dd"></script>
|
|
27
27
|
</head>
|
|
28
28
|
<body>
|
|
29
29
|
<div class="admin-container admin-root">
|
|
@@ -879,10 +879,10 @@
|
|
|
879
879
|
}
|
|
880
880
|
}
|
|
881
881
|
|
|
882
|
-
// Graph logic was extracted to js/admin.graph.js?v=1.26.
|
|
882
|
+
// Graph logic was extracted to js/admin.graph.js?v=1.26.11-9badd8dd
|
|
883
883
|
// Functions available globally: reloadGraphMermaid, initGraphScopeDefaults, copyMermaidSource, toggleGraphEdit, applyGraphEdit, cancelGraphEdit, refreshDrillCategories, loadDrillInstructions, clearSelections
|
|
884
884
|
|
|
885
|
-
<!-- overview functions moved to js/admin.overview.js?v=1.26.
|
|
885
|
+
<!-- overview functions moved to js/admin.overview.js?v=1.26.11-9badd8dd -->
|
|
886
886
|
|
|
887
887
|
// Lightweight overview-level maintenance display (optional)
|
|
888
888
|
// Intentionally minimal to avoid blocking overview rendering.
|
|
@@ -1067,7 +1067,7 @@
|
|
|
1067
1067
|
}
|
|
1068
1068
|
|
|
1069
1069
|
// --- Backup / Restore ---
|
|
1070
|
-
// Extracted to js/admin.maintenance.js?v=1.26.
|
|
1070
|
+
// Extracted to js/admin.maintenance.js?v=1.26.11-9badd8dd
|
|
1071
1071
|
|
|
1072
1072
|
async function performBackup() {
|
|
1073
1073
|
try {
|
|
@@ -1133,7 +1133,7 @@
|
|
|
1133
1133
|
}
|
|
1134
1134
|
|
|
1135
1135
|
async function loadConfiguration() {
|
|
1136
|
-
// Primary implementation in js/admin.config.js?v=1.26.
|
|
1136
|
+
// Primary implementation in js/admin.config.js?v=1.26.11-9badd8dd (loaded via defer).
|
|
1137
1137
|
// This inline fallback only fires if the external script failed to load.
|
|
1138
1138
|
if (window.__configExternalLoaded) return;
|
|
1139
1139
|
try {
|
|
@@ -1193,10 +1193,10 @@
|
|
|
1193
1193
|
return false;
|
|
1194
1194
|
}
|
|
1195
1195
|
|
|
1196
|
-
// Monitoring functions moved to js/admin.monitor.js?v=1.26.
|
|
1196
|
+
// Monitoring functions moved to js/admin.monitor.js?v=1.26.11-9badd8dd
|
|
1197
1197
|
|
|
1198
1198
|
// ===== Log Viewer =====
|
|
1199
|
-
// Extracted to js/admin.logs.js?v=1.26.
|
|
1199
|
+
// Extracted to js/admin.logs.js?v=1.26.11-9badd8dd
|
|
1200
1200
|
|
|
1201
1201
|
// ===== Instruction Management =====
|
|
1202
1202
|
let instructionEditing = null;
|
|
@@ -1693,7 +1693,7 @@
|
|
|
1693
1693
|
setInterval(fetchResourceTrends, 10000);
|
|
1694
1694
|
})();
|
|
1695
1695
|
|
|
1696
|
-
// Instruction management logic extracted to js/admin.instructions.js?v=1.26.
|
|
1696
|
+
// Instruction management logic extracted to js/admin.instructions.js?v=1.26.11-9badd8dd
|
|
1697
1697
|
// Functions exposed globally: loadInstructions, renderInstructionList, editInstruction, saveInstruction, deleteInstruction, etc.
|
|
1698
1698
|
|
|
1699
1699
|
function startAutoRefresh() {
|
|
@@ -112,6 +112,7 @@ export declare class McpStdioLogger {
|
|
|
112
112
|
private readonly _serverName;
|
|
113
113
|
private readonly _maxBufferSize;
|
|
114
114
|
private readonly _inferLevel;
|
|
115
|
+
private readonly _exitHandler;
|
|
115
116
|
constructor(options?: McpStdioLoggerOptions);
|
|
116
117
|
/**
|
|
117
118
|
* Start intercepting process.stderr.write.
|
|
@@ -152,6 +153,17 @@ export declare class McpStdioLogger {
|
|
|
152
153
|
* without triggering the MCP routing/buffering pipeline.
|
|
153
154
|
*/
|
|
154
155
|
writeOriginalStderr(data: string): void;
|
|
156
|
+
/**
|
|
157
|
+
* Drain the pre-handshake buffer to the ORIGINAL stderr without requiring
|
|
158
|
+
* an MCP server activation. Used when the process is about to exit before
|
|
159
|
+
* the MCP handshake completes (e.g., `--help`, `--init-cert`, or a fatal
|
|
160
|
+
* startup error). Without this, buffered diagnostic lines would be silently
|
|
161
|
+
* discarded — see issue #234.
|
|
162
|
+
*
|
|
163
|
+
* Safe to call repeatedly; a no-op when the buffer is empty. Does not change
|
|
164
|
+
* `isActive` and does not require a registered server.
|
|
165
|
+
*/
|
|
166
|
+
flushToStderr(): void;
|
|
155
167
|
/**
|
|
156
168
|
* Restore original stderr and deactivate the bridge.
|
|
157
169
|
* Useful for testing cleanup or graceful shutdown.
|
|
@@ -115,6 +115,7 @@ class McpStdioLogger {
|
|
|
115
115
|
_serverName;
|
|
116
116
|
_maxBufferSize;
|
|
117
117
|
_inferLevel;
|
|
118
|
+
_exitHandler;
|
|
118
119
|
constructor(options = {}) {
|
|
119
120
|
this._serverName = options.serverName ?? 'mcp-server';
|
|
120
121
|
this._maxBufferSize = options.maxBufferSize ?? 500;
|
|
@@ -123,6 +124,16 @@ class McpStdioLogger {
|
|
|
123
124
|
if (options.interceptImmediately !== false) {
|
|
124
125
|
this.interceptStderr();
|
|
125
126
|
}
|
|
127
|
+
// Issue #234: if the process exits before the MCP handshake completes
|
|
128
|
+
// (e.g. --help, --init-cert, fatal startup error), drain buffered stderr
|
|
129
|
+
// so the user actually sees what was logged. Inactive bridge only —
|
|
130
|
+
// once activated, the buffer is already replayed via sendLoggingMessage.
|
|
131
|
+
this._exitHandler = () => {
|
|
132
|
+
if (!this._active && this._buffer.length > 0) {
|
|
133
|
+
this.flushToStderr();
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
process.on('exit', this._exitHandler);
|
|
126
137
|
}
|
|
127
138
|
// -----------------------------------------------------------------------
|
|
128
139
|
// Public API
|
|
@@ -241,6 +252,30 @@ class McpStdioLogger {
|
|
|
241
252
|
}
|
|
242
253
|
catch { /* ignore */ }
|
|
243
254
|
}
|
|
255
|
+
/**
|
|
256
|
+
* Drain the pre-handshake buffer to the ORIGINAL stderr without requiring
|
|
257
|
+
* an MCP server activation. Used when the process is about to exit before
|
|
258
|
+
* the MCP handshake completes (e.g., `--help`, `--init-cert`, or a fatal
|
|
259
|
+
* startup error). Without this, buffered diagnostic lines would be silently
|
|
260
|
+
* discarded — see issue #234.
|
|
261
|
+
*
|
|
262
|
+
* Safe to call repeatedly; a no-op when the buffer is empty. Does not change
|
|
263
|
+
* `isActive` and does not require a registered server.
|
|
264
|
+
*/
|
|
265
|
+
flushToStderr() {
|
|
266
|
+
if (this._buffer.length === 0)
|
|
267
|
+
return;
|
|
268
|
+
for (const entry of this._buffer) {
|
|
269
|
+
const data = entry.data;
|
|
270
|
+
try {
|
|
271
|
+
this._originalStderrWrite(data.endsWith('\n') ? data : data + '\n');
|
|
272
|
+
}
|
|
273
|
+
catch {
|
|
274
|
+
/* ignore — best-effort drain */
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
this._buffer.length = 0;
|
|
278
|
+
}
|
|
244
279
|
/**
|
|
245
280
|
* Restore original stderr and deactivate the bridge.
|
|
246
281
|
* Useful for testing cleanup or graceful shutdown.
|
|
@@ -250,6 +285,10 @@ class McpStdioLogger {
|
|
|
250
285
|
this._active = false;
|
|
251
286
|
this._intercepting = false;
|
|
252
287
|
this._buffer.length = 0;
|
|
288
|
+
try {
|
|
289
|
+
process.removeListener('exit', this._exitHandler);
|
|
290
|
+
}
|
|
291
|
+
catch { /* ignore */ }
|
|
253
292
|
}
|
|
254
293
|
/**
|
|
255
294
|
* Get the number of currently buffered lines (pre-handshake).
|
package/dist/services/logger.js
CHANGED
|
@@ -60,6 +60,8 @@ function shouldEmit(level) {
|
|
|
60
60
|
const recordPriority = LEVEL_PRIORITY[level] ?? LEVEL_PRIORITY.INFO;
|
|
61
61
|
return recordPriority >= threshold;
|
|
62
62
|
}
|
|
63
|
+
// Single exit handler — registered once to avoid listener accumulation on re-init
|
|
64
|
+
let exitHandlerRegistered = false;
|
|
63
65
|
// Initialize file logging if INDEX_SERVER_LOG_FILE is specified
|
|
64
66
|
function initializeFileLogging() {
|
|
65
67
|
const cfg = loggingCfg();
|
|
@@ -89,6 +91,16 @@ function initializeFileLogging() {
|
|
|
89
91
|
encoding: 'utf8'
|
|
90
92
|
});
|
|
91
93
|
logFilePath = logFile;
|
|
94
|
+
// Graceful fallback: if the stream hits EPERM/EACCES, disable file logging
|
|
95
|
+
logFileHandle.on('error', (err) => {
|
|
96
|
+
process.stderr.write(`[logger] File logging error (${err.code ?? err.message}), falling back to stderr-only\n`);
|
|
97
|
+
try {
|
|
98
|
+
logFileHandle?.end();
|
|
99
|
+
}
|
|
100
|
+
catch { /* ignore */ }
|
|
101
|
+
logFileHandle = null;
|
|
102
|
+
logFilePath = undefined;
|
|
103
|
+
});
|
|
92
104
|
// NDJSON session start record
|
|
93
105
|
const sessionStart = {
|
|
94
106
|
ts: new Date().toISOString(),
|
|
@@ -98,19 +110,22 @@ function initializeFileLogging() {
|
|
|
98
110
|
};
|
|
99
111
|
const startLine = JSON.stringify(sessionStart);
|
|
100
112
|
logFileHandle.write(startLine + '\n');
|
|
101
|
-
// Cleanup on process exit
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
113
|
+
// Cleanup on process exit — register only once
|
|
114
|
+
if (!exitHandlerRegistered) {
|
|
115
|
+
exitHandlerRegistered = true;
|
|
116
|
+
process.on('exit', () => {
|
|
117
|
+
if (logFileHandle && !logFileHandle.destroyed) {
|
|
118
|
+
const sessionEnd = {
|
|
119
|
+
ts: new Date().toISOString(),
|
|
120
|
+
level: 'INFO',
|
|
121
|
+
msg: '[logger] Session ended',
|
|
122
|
+
pid: process.pid,
|
|
123
|
+
};
|
|
124
|
+
logFileHandle.write(JSON.stringify(sessionEnd) + '\n');
|
|
125
|
+
logFileHandle.end();
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
}
|
|
114
129
|
// Emit NDJSON init diagnostic
|
|
115
130
|
try {
|
|
116
131
|
const stats = fs_1.default.existsSync(logFile) ? fs_1.default.statSync(logFile) : null;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jagilber-org/index-server",
|
|
3
|
-
"version": "1.26.
|
|
3
|
+
"version": "1.26.11",
|
|
4
4
|
"mcpName": "io.github.jagilber-org/index-server",
|
|
5
5
|
"description": "MCP instruction indexing server for AI assistant governance — search, CRUD, schema validation, usage tracking, and cross-repo knowledge promotion.",
|
|
6
6
|
"publishConfig": {
|
|
@@ -50,6 +50,7 @@
|
|
|
50
50
|
"manifest:generate": "node scripts/generate-manifest.mjs",
|
|
51
51
|
"contract:tools": "node scripts/generate-tools-snapshot.mjs",
|
|
52
52
|
"verify:manifest": "node scripts/verify-manifest.mjs",
|
|
53
|
+
"check:version-parity": "node scripts/check-version-parity.mjs",
|
|
53
54
|
"test": "npm run test:fast",
|
|
54
55
|
"test:all": "vitest run",
|
|
55
56
|
"test:watch": "vitest",
|