@dollhousemcp/mcp-server 2.0.27 → 2.0.29
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 +13 -0
- package/dist/generated/version.d.ts +2 -2
- package/dist/generated/version.js +3 -3
- package/dist/handlers/mcp-aql/OperationSchema.js +2 -2
- package/dist/handlers/mcp-aql/evaluatePermission.d.ts.map +1 -1
- package/dist/handlers/mcp-aql/evaluatePermission.js +9 -3
- package/dist/services/BuildInfoService.d.ts +6 -1
- package/dist/services/BuildInfoService.d.ts.map +1 -1
- package/dist/services/BuildInfoService.js +23 -3
- package/dist/tools/portfolio/submitToPortfolioTool.d.ts.map +1 -1
- package/dist/tools/portfolio/submitToPortfolioTool.js +4 -3
- package/dist/utils/permissionHooks.d.ts +18 -0
- package/dist/utils/permissionHooks.d.ts.map +1 -1
- package/dist/utils/permissionHooks.js +182 -15
- package/dist/web/console/IngestRoutes.d.ts +7 -1
- package/dist/web/console/IngestRoutes.d.ts.map +1 -1
- package/dist/web/console/IngestRoutes.js +28 -6
- package/dist/web/console/LeaderForwardingSink.d.ts +6 -1
- package/dist/web/console/LeaderForwardingSink.d.ts.map +1 -1
- package/dist/web/console/LeaderForwardingSink.js +8 -2
- package/dist/web/console/UnifiedConsole.d.ts.map +1 -1
- package/dist/web/console/UnifiedConsole.js +6 -3
- package/dist/web/console/sessionClientPlatform.d.ts +11 -0
- package/dist/web/console/sessionClientPlatform.d.ts.map +1 -0
- package/dist/web/console/sessionClientPlatform.js +83 -0
- package/dist/web/public/permissions.js +10 -0
- package/dist/web/public/sessions.css +89 -9
- package/dist/web/public/sessions.js +160 -4
- package/dist/web/public/setup.js +40 -0
- package/dist/web/routes/permissionRoutes.d.ts +1 -0
- package/dist/web/routes/permissionRoutes.d.ts.map +1 -1
- package/dist/web/routes/permissionRoutes.js +17 -7
- package/dist/web/routes/setupRoutes.d.ts +5 -1
- package/dist/web/routes/setupRoutes.d.ts.map +1 -1
- package/dist/web/routes/setupRoutes.js +28 -14
- package/dist/web/server.d.ts.map +1 -1
- package/dist/web/server.js +5 -1
- package/package.json +1 -1
- package/scripts/pretooluse-dollhouse.sh +36 -2
- package/scripts/pretooluse-vscode.sh +5 -2
- package/scripts/pretooluse-windsurf.sh +5 -2
- package/server.json +2 -2
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Best-effort MCP client platform detection for session metadata.
|
|
3
|
+
*
|
|
4
|
+
* This is intentionally conservative: when we cannot identify the host
|
|
5
|
+
* confidently, we return null rather than guessing from a session ID.
|
|
6
|
+
*/
|
|
7
|
+
const CLIENT_PLATFORM_LABELS = {
|
|
8
|
+
'claude-code': 'Claude Code',
|
|
9
|
+
'claude-desktop': 'Claude Desktop',
|
|
10
|
+
codex: 'Codex',
|
|
11
|
+
cursor: 'Cursor',
|
|
12
|
+
vscode: 'VS Code',
|
|
13
|
+
windsurf: 'Windsurf',
|
|
14
|
+
'gemini-cli': 'Gemini CLI',
|
|
15
|
+
cline: 'Cline',
|
|
16
|
+
lmstudio: 'LM Studio',
|
|
17
|
+
'web-console': 'Web Console',
|
|
18
|
+
};
|
|
19
|
+
function normalizeText(value) {
|
|
20
|
+
return typeof value === 'string' ? value.trim().toLowerCase() : '';
|
|
21
|
+
}
|
|
22
|
+
function includesAny(value, needles) {
|
|
23
|
+
return needles.some((needle) => value.includes(needle));
|
|
24
|
+
}
|
|
25
|
+
function matchesAnySource(values, needles) {
|
|
26
|
+
return values.some((value) => includesAny(value, needles));
|
|
27
|
+
}
|
|
28
|
+
const TEXT_PLATFORM_MATCHERS = [
|
|
29
|
+
{ platform: 'cursor', needles: ['cursor'] },
|
|
30
|
+
{ platform: 'windsurf', needles: ['windsurf'] },
|
|
31
|
+
{ platform: 'gemini-cli', needles: ['gemini'] },
|
|
32
|
+
{ platform: 'cline', needles: ['cline'] },
|
|
33
|
+
{ platform: 'lmstudio', needles: ['lmstudio', 'lm studio'] },
|
|
34
|
+
{ platform: 'claude-desktop', needles: ['claude desktop'] },
|
|
35
|
+
{ platform: 'claude-code', needles: ['claude code'] },
|
|
36
|
+
{ platform: 'codex', needles: ['codex'] },
|
|
37
|
+
];
|
|
38
|
+
export function normalizeSessionClientPlatformId(value) {
|
|
39
|
+
const normalized = normalizeText(value ?? undefined);
|
|
40
|
+
if (!normalized) {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
if (normalized === 'gemini') {
|
|
44
|
+
return 'gemini-cli';
|
|
45
|
+
}
|
|
46
|
+
if (normalized in CLIENT_PLATFORM_LABELS) {
|
|
47
|
+
return normalized;
|
|
48
|
+
}
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
export function getSessionClientPlatformLabel(platform) {
|
|
52
|
+
return platform ? CLIENT_PLATFORM_LABELS[platform] ?? '' : '';
|
|
53
|
+
}
|
|
54
|
+
export function detectSessionClientPlatformId(env = process.env, argv = process.argv, execPath = process.execPath, title = process.title) {
|
|
55
|
+
const termProgram = normalizeText(env.TERM_PROGRAM);
|
|
56
|
+
const argvText = normalizeText(argv.join(' '));
|
|
57
|
+
const execPathText = normalizeText(execPath);
|
|
58
|
+
const titleText = normalizeText(title);
|
|
59
|
+
const textSources = [argvText, execPathText, titleText];
|
|
60
|
+
if (env.CLAUDE_DESKTOP === 'true' || env.CLAUDE_DESKTOP_VERSION) {
|
|
61
|
+
return 'claude-desktop';
|
|
62
|
+
}
|
|
63
|
+
if (env.CLAUDE_CODE === 'true' || termProgram === 'claude-code') {
|
|
64
|
+
return 'claude-code';
|
|
65
|
+
}
|
|
66
|
+
if (env.VSCODE_CWD ||
|
|
67
|
+
env.VSCODE_PID ||
|
|
68
|
+
env.VSCODE_IPC_HOOK ||
|
|
69
|
+
env.VSCODE_NLS_CONFIG ||
|
|
70
|
+
termProgram === 'vscode') {
|
|
71
|
+
return 'vscode';
|
|
72
|
+
}
|
|
73
|
+
if (env.CODEX_HOME || termProgram === 'codex') {
|
|
74
|
+
return 'codex';
|
|
75
|
+
}
|
|
76
|
+
for (const matcher of TEXT_PLATFORM_MATCHERS) {
|
|
77
|
+
if (matchesAnySource(textSources, matcher.needles)) {
|
|
78
|
+
return matcher.platform;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2Vzc2lvbkNsaWVudFBsYXRmb3JtLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3dlYi9jb25zb2xlL3Nlc3Npb25DbGllbnRQbGF0Zm9ybS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7R0FLRztBQWNILE1BQU0sc0JBQXNCLEdBQTRDO0lBQ3RFLGFBQWEsRUFBRSxhQUFhO0lBQzVCLGdCQUFnQixFQUFFLGdCQUFnQjtJQUNsQyxLQUFLLEVBQUUsT0FBTztJQUNkLE1BQU0sRUFBRSxRQUFRO0lBQ2hCLE1BQU0sRUFBRSxTQUFTO0lBQ2pCLFFBQVEsRUFBRSxVQUFVO0lBQ3BCLFlBQVksRUFBRSxZQUFZO0lBQzFCLEtBQUssRUFBRSxPQUFPO0lBQ2QsUUFBUSxFQUFFLFdBQVc7SUFDckIsYUFBYSxFQUFFLGFBQWE7Q0FDN0IsQ0FBQztBQUVGLFNBQVMsYUFBYSxDQUFDLEtBQXlCO0lBQzlDLE9BQU8sT0FBTyxLQUFLLEtBQUssUUFBUSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsSUFBSSxFQUFFLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztBQUNyRSxDQUFDO0FBRUQsU0FBUyxXQUFXLENBQUMsS0FBYSxFQUFFLE9BQTBCO0lBQzVELE9BQU8sT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO0FBQzFELENBQUM7QUFFRCxTQUFTLGdCQUFnQixDQUFDLE1BQXlCLEVBQUUsT0FBMEI7SUFDN0UsT0FBTyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxXQUFXLENBQUMsS0FBSyxFQUFFLE9BQU8sQ0FBQyxDQUFDLENBQUM7QUFDN0QsQ0FBQztBQUVELE1BQU0sc0JBQXNCLEdBR3ZCO0lBQ0gsRUFBRSxRQUFRLEVBQUUsUUFBUSxFQUFFLE9BQU8sRUFBRSxDQUFDLFFBQVEsQ0FBQyxFQUFFO0lBQzNDLEVBQUUsUUFBUSxFQUFFLFVBQVUsRUFBRSxPQUFPLEVBQUUsQ0FBQyxVQUFVLENBQUMsRUFBRTtJQUMvQyxFQUFFLFFBQVEsRUFBRSxZQUFZLEVBQUUsT0FBTyxFQUFFLENBQUMsUUFBUSxDQUFDLEVBQUU7SUFDL0MsRUFBRSxRQUFRLEVBQUUsT0FBTyxFQUFFLE9BQU8sRUFBRSxDQUFDLE9BQU8sQ0FBQyxFQUFFO0lBQ3pDLEVBQUUsUUFBUSxFQUFFLFVBQVUsRUFBRSxPQUFPLEVBQUUsQ0FBQyxVQUFVLEVBQUUsV0FBVyxDQUFDLEVBQUU7SUFDNUQsRUFBRSxRQUFRLEVBQUUsZ0JBQWdCLEVBQUUsT0FBTyxFQUFFLENBQUMsZ0JBQWdCLENBQUMsRUFBRTtJQUMzRCxFQUFFLFFBQVEsRUFBRSxhQUFhLEVBQUUsT0FBTyxFQUFFLENBQUMsYUFBYSxDQUFDLEVBQUU7SUFDckQsRUFBRSxRQUFRLEVBQUUsT0FBTyxFQUFFLE9BQU8sRUFBRSxDQUFDLE9BQU8sQ0FBQyxFQUFFO0NBQzFDLENBQUM7QUFFRixNQUFNLFVBQVUsZ0NBQWdDLENBQzlDLEtBQWdDO0lBRWhDLE1BQU0sVUFBVSxHQUFHLGFBQWEsQ0FBQyxLQUFLLElBQUksU0FBUyxDQUFDLENBQUM7SUFDckQsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO1FBQ2hCLE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztJQUVELElBQUksVUFBVSxLQUFLLFFBQVEsRUFBRSxDQUFDO1FBQzVCLE9BQU8sWUFBWSxDQUFDO0lBQ3RCLENBQUM7SUFFRCxJQUFJLFVBQVUsSUFBSSxzQkFBc0IsRUFBRSxDQUFDO1FBQ3pDLE9BQU8sVUFBcUMsQ0FBQztJQUMvQyxDQUFDO0lBRUQsT0FBTyxJQUFJLENBQUM7QUFDZCxDQUFDO0FBRUQsTUFBTSxVQUFVLDZCQUE2QixDQUMzQyxRQUFvRDtJQUVwRCxPQUFPLFFBQVEsQ0FBQyxDQUFDLENBQUMsc0JBQXNCLENBQUMsUUFBUSxDQUFDLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7QUFDaEUsQ0FBQztBQUVELE1BQU0sVUFBVSw2QkFBNkIsQ0FDM0MsTUFBeUIsT0FBTyxDQUFDLEdBQUcsRUFDcEMsT0FBMEIsT0FBTyxDQUFDLElBQUksRUFDdEMsV0FBbUIsT0FBTyxDQUFDLFFBQVEsRUFDbkMsUUFBZ0IsT0FBTyxDQUFDLEtBQUs7SUFFN0IsTUFBTSxXQUFXLEdBQUcsYUFBYSxDQUFDLEdBQUcsQ0FBQyxZQUFZLENBQUMsQ0FBQztJQUNwRCxNQUFNLFFBQVEsR0FBRyxhQUFhLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO0lBQy9DLE1BQU0sWUFBWSxHQUFHLGFBQWEsQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUM3QyxNQUFNLFNBQVMsR0FBRyxhQUFhLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDdkMsTUFBTSxXQUFXLEdBQUcsQ0FBQyxRQUFRLEVBQUUsWUFBWSxFQUFFLFNBQVMsQ0FBQyxDQUFDO0lBRXhELElBQUksR0FBRyxDQUFDLGNBQWMsS0FBSyxNQUFNLElBQUksR0FBRyxDQUFDLHNCQUFzQixFQUFFLENBQUM7UUFDaEUsT0FBTyxnQkFBZ0IsQ0FBQztJQUMxQixDQUFDO0lBRUQsSUFBSSxHQUFHLENBQUMsV0FBVyxLQUFLLE1BQU0sSUFBSSxXQUFXLEtBQUssYUFBYSxFQUFFLENBQUM7UUFDaEUsT0FBTyxhQUFhLENBQUM7SUFDdkIsQ0FBQztJQUVELElBQ0UsR0FBRyxDQUFDLFVBQVU7UUFDZCxHQUFHLENBQUMsVUFBVTtRQUNkLEdBQUcsQ0FBQyxlQUFlO1FBQ25CLEdBQUcsQ0FBQyxpQkFBaUI7UUFDckIsV0FBVyxLQUFLLFFBQVEsRUFDeEIsQ0FBQztRQUNELE9BQU8sUUFBUSxDQUFDO0lBQ2xCLENBQUM7SUFFRCxJQUFJLEdBQUcsQ0FBQyxVQUFVLElBQUksV0FBVyxLQUFLLE9BQU8sRUFBRSxDQUFDO1FBQzlDLE9BQU8sT0FBTyxDQUFDO0lBQ2pCLENBQUM7SUFFRCxLQUFLLE1BQU0sT0FBTyxJQUFJLHNCQUFzQixFQUFFLENBQUM7UUFDN0MsSUFBSSxnQkFBZ0IsQ0FBQyxXQUFXLEVBQUUsT0FBTyxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7WUFDbkQsT0FBTyxPQUFPLENBQUMsUUFBUSxDQUFDO1FBQzFCLENBQUM7SUFDSCxDQUFDO0lBRUQsT0FBTyxJQUFJLENBQUM7QUFDZCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBCZXN0LWVmZm9ydCBNQ1AgY2xpZW50IHBsYXRmb3JtIGRldGVjdGlvbiBmb3Igc2Vzc2lvbiBtZXRhZGF0YS5cbiAqXG4gKiBUaGlzIGlzIGludGVudGlvbmFsbHkgY29uc2VydmF0aXZlOiB3aGVuIHdlIGNhbm5vdCBpZGVudGlmeSB0aGUgaG9zdFxuICogY29uZmlkZW50bHksIHdlIHJldHVybiBudWxsIHJhdGhlciB0aGFuIGd1ZXNzaW5nIGZyb20gYSBzZXNzaW9uIElELlxuICovXG5cbmV4cG9ydCB0eXBlIFNlc3Npb25DbGllbnRQbGF0Zm9ybUlkID1cbiAgfCAnY2xhdWRlLWNvZGUnXG4gIHwgJ2NsYXVkZS1kZXNrdG9wJ1xuICB8ICdjb2RleCdcbiAgfCAnY3Vyc29yJ1xuICB8ICd2c2NvZGUnXG4gIHwgJ3dpbmRzdXJmJ1xuICB8ICdnZW1pbmktY2xpJ1xuICB8ICdjbGluZSdcbiAgfCAnbG1zdHVkaW8nXG4gIHwgJ3dlYi1jb25zb2xlJztcblxuY29uc3QgQ0xJRU5UX1BMQVRGT1JNX0xBQkVMUzogUmVjb3JkPFNlc3Npb25DbGllbnRQbGF0Zm9ybUlkLCBzdHJpbmc+ID0ge1xuICAnY2xhdWRlLWNvZGUnOiAnQ2xhdWRlIENvZGUnLFxuICAnY2xhdWRlLWRlc2t0b3AnOiAnQ2xhdWRlIERlc2t0b3AnLFxuICBjb2RleDogJ0NvZGV4JyxcbiAgY3Vyc29yOiAnQ3Vyc29yJyxcbiAgdnNjb2RlOiAnVlMgQ29kZScsXG4gIHdpbmRzdXJmOiAnV2luZHN1cmYnLFxuICAnZ2VtaW5pLWNsaSc6ICdHZW1pbmkgQ0xJJyxcbiAgY2xpbmU6ICdDbGluZScsXG4gIGxtc3R1ZGlvOiAnTE0gU3R1ZGlvJyxcbiAgJ3dlYi1jb25zb2xlJzogJ1dlYiBDb25zb2xlJyxcbn07XG5cbmZ1bmN0aW9uIG5vcm1hbGl6ZVRleHQodmFsdWU6IHN0cmluZyB8IHVuZGVmaW5lZCk6IHN0cmluZyB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnID8gdmFsdWUudHJpbSgpLnRvTG93ZXJDYXNlKCkgOiAnJztcbn1cblxuZnVuY3Rpb24gaW5jbHVkZXNBbnkodmFsdWU6IHN0cmluZywgbmVlZGxlczogcmVhZG9ubHkgc3RyaW5nW10pOiBib29sZWFuIHtcbiAgcmV0dXJuIG5lZWRsZXMuc29tZSgobmVlZGxlKSA9PiB2YWx1ZS5pbmNsdWRlcyhuZWVkbGUpKTtcbn1cblxuZnVuY3Rpb24gbWF0Y2hlc0FueVNvdXJjZSh2YWx1ZXM6IHJlYWRvbmx5IHN0cmluZ1tdLCBuZWVkbGVzOiByZWFkb25seSBzdHJpbmdbXSk6IGJvb2xlYW4ge1xuICByZXR1cm4gdmFsdWVzLnNvbWUoKHZhbHVlKSA9PiBpbmNsdWRlc0FueSh2YWx1ZSwgbmVlZGxlcykpO1xufVxuXG5jb25zdCBURVhUX1BMQVRGT1JNX01BVENIRVJTOiBSZWFkb25seUFycmF5PHtcbiAgcGxhdGZvcm06IFNlc3Npb25DbGllbnRQbGF0Zm9ybUlkO1xuICBuZWVkbGVzOiByZWFkb25seSBzdHJpbmdbXTtcbn0+ID0gW1xuICB7IHBsYXRmb3JtOiAnY3Vyc29yJywgbmVlZGxlczogWydjdXJzb3InXSB9LFxuICB7IHBsYXRmb3JtOiAnd2luZHN1cmYnLCBuZWVkbGVzOiBbJ3dpbmRzdXJmJ10gfSxcbiAgeyBwbGF0Zm9ybTogJ2dlbWluaS1jbGknLCBuZWVkbGVzOiBbJ2dlbWluaSddIH0sXG4gIHsgcGxhdGZvcm06ICdjbGluZScsIG5lZWRsZXM6IFsnY2xpbmUnXSB9LFxuICB7IHBsYXRmb3JtOiAnbG1zdHVkaW8nLCBuZWVkbGVzOiBbJ2xtc3R1ZGlvJywgJ2xtIHN0dWRpbyddIH0sXG4gIHsgcGxhdGZvcm06ICdjbGF1ZGUtZGVza3RvcCcsIG5lZWRsZXM6IFsnY2xhdWRlIGRlc2t0b3AnXSB9LFxuICB7IHBsYXRmb3JtOiAnY2xhdWRlLWNvZGUnLCBuZWVkbGVzOiBbJ2NsYXVkZSBjb2RlJ10gfSxcbiAgeyBwbGF0Zm9ybTogJ2NvZGV4JywgbmVlZGxlczogWydjb2RleCddIH0sXG5dO1xuXG5leHBvcnQgZnVuY3Rpb24gbm9ybWFsaXplU2Vzc2lvbkNsaWVudFBsYXRmb3JtSWQoXG4gIHZhbHVlOiBzdHJpbmcgfCBudWxsIHwgdW5kZWZpbmVkLFxuKTogU2Vzc2lvbkNsaWVudFBsYXRmb3JtSWQgfCBudWxsIHtcbiAgY29uc3Qgbm9ybWFsaXplZCA9IG5vcm1hbGl6ZVRleHQodmFsdWUgPz8gdW5kZWZpbmVkKTtcbiAgaWYgKCFub3JtYWxpemVkKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBpZiAobm9ybWFsaXplZCA9PT0gJ2dlbWluaScpIHtcbiAgICByZXR1cm4gJ2dlbWluaS1jbGknO1xuICB9XG5cbiAgaWYgKG5vcm1hbGl6ZWQgaW4gQ0xJRU5UX1BMQVRGT1JNX0xBQkVMUykge1xuICAgIHJldHVybiBub3JtYWxpemVkIGFzIFNlc3Npb25DbGllbnRQbGF0Zm9ybUlkO1xuICB9XG5cbiAgcmV0dXJuIG51bGw7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRTZXNzaW9uQ2xpZW50UGxhdGZvcm1MYWJlbChcbiAgcGxhdGZvcm06IFNlc3Npb25DbGllbnRQbGF0Zm9ybUlkIHwgbnVsbCB8IHVuZGVmaW5lZCxcbik6IHN0cmluZyB7XG4gIHJldHVybiBwbGF0Zm9ybSA/IENMSUVOVF9QTEFURk9STV9MQUJFTFNbcGxhdGZvcm1dID8/ICcnIDogJyc7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBkZXRlY3RTZXNzaW9uQ2xpZW50UGxhdGZvcm1JZChcbiAgZW52OiBOb2RlSlMuUHJvY2Vzc0VudiA9IHByb2Nlc3MuZW52LFxuICBhcmd2OiByZWFkb25seSBzdHJpbmdbXSA9IHByb2Nlc3MuYXJndixcbiAgZXhlY1BhdGg6IHN0cmluZyA9IHByb2Nlc3MuZXhlY1BhdGgsXG4gIHRpdGxlOiBzdHJpbmcgPSBwcm9jZXNzLnRpdGxlLFxuKTogU2Vzc2lvbkNsaWVudFBsYXRmb3JtSWQgfCBudWxsIHtcbiAgY29uc3QgdGVybVByb2dyYW0gPSBub3JtYWxpemVUZXh0KGVudi5URVJNX1BST0dSQU0pO1xuICBjb25zdCBhcmd2VGV4dCA9IG5vcm1hbGl6ZVRleHQoYXJndi5qb2luKCcgJykpO1xuICBjb25zdCBleGVjUGF0aFRleHQgPSBub3JtYWxpemVUZXh0KGV4ZWNQYXRoKTtcbiAgY29uc3QgdGl0bGVUZXh0ID0gbm9ybWFsaXplVGV4dCh0aXRsZSk7XG4gIGNvbnN0IHRleHRTb3VyY2VzID0gW2FyZ3ZUZXh0LCBleGVjUGF0aFRleHQsIHRpdGxlVGV4dF07XG5cbiAgaWYgKGVudi5DTEFVREVfREVTS1RPUCA9PT0gJ3RydWUnIHx8IGVudi5DTEFVREVfREVTS1RPUF9WRVJTSU9OKSB7XG4gICAgcmV0dXJuICdjbGF1ZGUtZGVza3RvcCc7XG4gIH1cblxuICBpZiAoZW52LkNMQVVERV9DT0RFID09PSAndHJ1ZScgfHwgdGVybVByb2dyYW0gPT09ICdjbGF1ZGUtY29kZScpIHtcbiAgICByZXR1cm4gJ2NsYXVkZS1jb2RlJztcbiAgfVxuXG4gIGlmIChcbiAgICBlbnYuVlNDT0RFX0NXRCB8fFxuICAgIGVudi5WU0NPREVfUElEIHx8XG4gICAgZW52LlZTQ09ERV9JUENfSE9PSyB8fFxuICAgIGVudi5WU0NPREVfTkxTX0NPTkZJRyB8fFxuICAgIHRlcm1Qcm9ncmFtID09PSAndnNjb2RlJ1xuICApIHtcbiAgICByZXR1cm4gJ3ZzY29kZSc7XG4gIH1cblxuICBpZiAoZW52LkNPREVYX0hPTUUgfHwgdGVybVByb2dyYW0gPT09ICdjb2RleCcpIHtcbiAgICByZXR1cm4gJ2NvZGV4JztcbiAgfVxuXG4gIGZvciAoY29uc3QgbWF0Y2hlciBvZiBURVhUX1BMQVRGT1JNX01BVENIRVJTKSB7XG4gICAgaWYgKG1hdGNoZXNBbnlTb3VyY2UodGV4dFNvdXJjZXMsIG1hdGNoZXIubmVlZGxlcykpIHtcbiAgICAgIHJldHVybiBtYXRjaGVyLnBsYXRmb3JtO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBudWxsO1xufVxuIl19
|
|
@@ -225,6 +225,16 @@
|
|
|
225
225
|
} else if (data.permissionPromptActive) {
|
|
226
226
|
hookDot.dataset.status = 'active';
|
|
227
227
|
hookLabel.textContent = 'Prompt tool active';
|
|
228
|
+
} else if (data.hookNeedsRepair) {
|
|
229
|
+
hookDot.dataset.status = 'warning';
|
|
230
|
+
hookLabel.textContent = data.hookHost
|
|
231
|
+
? `Hook needs repair (${data.hookHost})`
|
|
232
|
+
: 'Hook needs repair';
|
|
233
|
+
} else if (data.hookAutoRepaired) {
|
|
234
|
+
hookDot.dataset.status = 'active';
|
|
235
|
+
hookLabel.textContent = data.hookHost
|
|
236
|
+
? `Hook refreshed (${data.hookHost})`
|
|
237
|
+
: 'Hook refreshed';
|
|
228
238
|
} else if (data.hookInstalled) {
|
|
229
239
|
hookDot.dataset.status = 'active';
|
|
230
240
|
hookLabel.textContent = data.hookHost ? `Hook installed (${data.hookHost})` : 'Hook installed';
|
|
@@ -66,7 +66,8 @@
|
|
|
66
66
|
position: absolute;
|
|
67
67
|
top: calc(100% + 0.4rem);
|
|
68
68
|
right: 0;
|
|
69
|
-
|
|
69
|
+
width: min(34rem, calc(100vw - 1rem));
|
|
70
|
+
box-sizing: border-box;
|
|
70
71
|
background: var(--paper-strong, #fff);
|
|
71
72
|
border: 1px solid var(--line, #c8d5e9);
|
|
72
73
|
border-radius: var(--radius-md, 0.85rem);
|
|
@@ -184,10 +185,11 @@
|
|
|
184
185
|
|
|
185
186
|
.session-dropdown-item {
|
|
186
187
|
display: grid;
|
|
187
|
-
grid-template-columns: 1rem 8px 1fr
|
|
188
|
+
grid-template-columns: 1rem 8px minmax(0, 1fr) 5.5rem 6.75rem 4.5rem 1.2rem;
|
|
188
189
|
align-items: center;
|
|
189
|
-
gap: 0.
|
|
190
|
-
|
|
190
|
+
column-gap: 0.7rem;
|
|
191
|
+
row-gap: 0.3rem;
|
|
192
|
+
padding: 0.55rem 0.9rem;
|
|
191
193
|
font-size: var(--step--1, 0.82rem);
|
|
192
194
|
cursor: pointer;
|
|
193
195
|
transition: background 0.1s;
|
|
@@ -235,12 +237,51 @@
|
|
|
235
237
|
white-space: nowrap;
|
|
236
238
|
}
|
|
237
239
|
|
|
240
|
+
.session-dropdown-primary {
|
|
241
|
+
min-width: 0;
|
|
242
|
+
display: flex;
|
|
243
|
+
flex-direction: column;
|
|
244
|
+
gap: 0.18rem;
|
|
245
|
+
align-self: center;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
.session-dropdown-meta {
|
|
249
|
+
display: flex;
|
|
250
|
+
align-items: center;
|
|
251
|
+
gap: 0.35rem;
|
|
252
|
+
min-width: 0;
|
|
253
|
+
flex-wrap: wrap;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
.session-dropdown-version {
|
|
257
|
+
font-size: 0.7rem;
|
|
258
|
+
font-family: var(--font-mono, monospace);
|
|
259
|
+
color: var(--ink-500, #677893);
|
|
260
|
+
white-space: nowrap;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
.session-dropdown-update {
|
|
264
|
+
display: inline-flex;
|
|
265
|
+
align-items: center;
|
|
266
|
+
padding: 1px 5px;
|
|
267
|
+
border-radius: 999px;
|
|
268
|
+
font-size: 0.62rem;
|
|
269
|
+
font-weight: 700;
|
|
270
|
+
letter-spacing: 0.04em;
|
|
271
|
+
background: #ecfdf5;
|
|
272
|
+
color: #166534;
|
|
273
|
+
border: 1px solid #86efac;
|
|
274
|
+
white-space: nowrap;
|
|
275
|
+
}
|
|
276
|
+
|
|
238
277
|
.session-dropdown-uptime {
|
|
239
278
|
font-size: 0.7rem;
|
|
240
279
|
font-family: var(--font-mono, monospace);
|
|
241
280
|
color: var(--ink-500, #677893);
|
|
242
281
|
white-space: nowrap;
|
|
243
282
|
text-align: right;
|
|
283
|
+
min-width: 4.5rem;
|
|
284
|
+
justify-self: end;
|
|
244
285
|
}
|
|
245
286
|
|
|
246
287
|
.session-dropdown-role {
|
|
@@ -287,6 +328,16 @@
|
|
|
287
328
|
color: var(--ink-900, #e0e8f0);
|
|
288
329
|
}
|
|
289
330
|
|
|
331
|
+
[data-theme="dark"] .session-dropdown-version {
|
|
332
|
+
color: var(--ink-500, #8899bb);
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
[data-theme="dark"] .session-dropdown-update {
|
|
336
|
+
background: #052e16;
|
|
337
|
+
color: #bbf7d0;
|
|
338
|
+
border-color: #166534;
|
|
339
|
+
}
|
|
340
|
+
|
|
290
341
|
[data-theme="dark"] .session-dropdown-toggle-label {
|
|
291
342
|
color: var(--ink-500, #8899bb);
|
|
292
343
|
}
|
|
@@ -363,15 +414,40 @@
|
|
|
363
414
|
* - Color (blue=positive, orange=negative — colorblind-safe pair)
|
|
364
415
|
*/
|
|
365
416
|
.session-status-badge {
|
|
366
|
-
display: inline-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
417
|
+
display: inline-flex;
|
|
418
|
+
align-items: center;
|
|
419
|
+
justify-content: center;
|
|
420
|
+
padding: 2px 7px;
|
|
421
|
+
border-radius: 5px;
|
|
422
|
+
font-size: 10px;
|
|
370
423
|
font-weight: 600;
|
|
371
424
|
letter-spacing: 0.04em;
|
|
372
425
|
white-space: nowrap;
|
|
373
426
|
text-align: center;
|
|
374
|
-
min-width:
|
|
427
|
+
min-width: 4.75rem;
|
|
428
|
+
box-sizing: border-box;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
.session-dropdown-item > .session-status-badge {
|
|
432
|
+
justify-self: center;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
.session-dropdown-badge-stack {
|
|
436
|
+
display: flex;
|
|
437
|
+
flex-direction: column;
|
|
438
|
+
align-items: center;
|
|
439
|
+
justify-self: center;
|
|
440
|
+
gap: 0.24rem;
|
|
441
|
+
width: 100%;
|
|
442
|
+
max-width: 6.75rem;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
.session-dropdown-client-label {
|
|
446
|
+
font-size: 0.62rem;
|
|
447
|
+
line-height: 1.15;
|
|
448
|
+
color: var(--ink-500, #677893);
|
|
449
|
+
text-align: center;
|
|
450
|
+
width: 100%;
|
|
375
451
|
}
|
|
376
452
|
|
|
377
453
|
.session-status-badge[data-status="positive"] {
|
|
@@ -398,6 +474,10 @@
|
|
|
398
474
|
border-color: #9a3412;
|
|
399
475
|
}
|
|
400
476
|
|
|
477
|
+
[data-theme="dark"] .session-dropdown-client-label {
|
|
478
|
+
color: var(--ink-500, #8899bb);
|
|
479
|
+
}
|
|
480
|
+
|
|
401
481
|
/* Session filter in the log viewer */
|
|
402
482
|
#log-session-filter {
|
|
403
483
|
min-width: 120px;
|
|
@@ -33,6 +33,18 @@
|
|
|
33
33
|
var lastReloadTargetVersion = '';
|
|
34
34
|
var pendingLeaderReloadTimer = null;
|
|
35
35
|
var showPolicySessions = loadPolicyDebugVisibility();
|
|
36
|
+
var CLIENT_PLATFORM_LABELS = {
|
|
37
|
+
'claude-code': 'Claude Code',
|
|
38
|
+
'claude-desktop': 'Claude Desktop',
|
|
39
|
+
'codex': 'Codex',
|
|
40
|
+
'cursor': 'Cursor',
|
|
41
|
+
'vscode': 'VS Code',
|
|
42
|
+
'windsurf': 'Windsurf',
|
|
43
|
+
'gemini-cli': 'Gemini CLI',
|
|
44
|
+
'cline': 'Cline',
|
|
45
|
+
'lmstudio': 'LM Studio',
|
|
46
|
+
'web-console': 'Web Console'
|
|
47
|
+
};
|
|
36
48
|
|
|
37
49
|
function loadPolicyDebugVisibility() {
|
|
38
50
|
try {
|
|
@@ -176,6 +188,55 @@
|
|
|
176
188
|
/** NFC-normalize a string safely */
|
|
177
189
|
function nfc(s) { try { return s.normalize('NFC'); } catch(e) { return s; } }
|
|
178
190
|
|
|
191
|
+
function normalizeClientPlatform(platform) {
|
|
192
|
+
if (typeof platform !== 'string') return '';
|
|
193
|
+
var normalized = nfc(platform).trim().toLowerCase();
|
|
194
|
+
if (!normalized) return '';
|
|
195
|
+
if (normalized === 'gemini') return 'gemini-cli';
|
|
196
|
+
return Object.prototype.hasOwnProperty.call(CLIENT_PLATFORM_LABELS, normalized) ? normalized : '';
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
function displayPlatform(session) {
|
|
200
|
+
if (!session || typeof session !== 'object') return '';
|
|
201
|
+
if (typeof session.clientPlatformLabel === 'string' && session.clientPlatformLabel.trim()) {
|
|
202
|
+
return nfc(session.clientPlatformLabel.trim());
|
|
203
|
+
}
|
|
204
|
+
var platform = normalizeClientPlatform(session.clientPlatform);
|
|
205
|
+
return platform ? CLIENT_PLATFORM_LABELS[platform] || '' : '';
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
function displayVersion(session) {
|
|
209
|
+
if (!session || typeof session !== 'object') return '';
|
|
210
|
+
var normalized = normalizeSemver(session.serverVersion);
|
|
211
|
+
if (!normalized && typeof session.serverVersion === 'string') {
|
|
212
|
+
normalized = nfc(session.serverVersion).trim();
|
|
213
|
+
}
|
|
214
|
+
if (!normalized) return '';
|
|
215
|
+
return normalized.charAt(0) === 'v' ? normalized : ('v' + normalized);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
function getNewestKnownSessionVersion(list) {
|
|
219
|
+
if (!Array.isArray(list)) return '';
|
|
220
|
+
var newest = '';
|
|
221
|
+
for (var i = 0; i < list.length; i++) {
|
|
222
|
+
var session = list[i];
|
|
223
|
+
if (!session || isPolicyOnlySession(session) || session.status !== 'active') continue;
|
|
224
|
+
var version = normalizeSemver(session.serverVersion);
|
|
225
|
+
if (!version) continue;
|
|
226
|
+
if (!newest || compareSemver(version, newest) > 0) {
|
|
227
|
+
newest = version;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
return newest;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
function sessionHasUpdateAvailable(session, newestVersion) {
|
|
234
|
+
if (!session || !newestVersion || isPolicyOnlySession(session)) return false;
|
|
235
|
+
var version = normalizeSemver(session.serverVersion);
|
|
236
|
+
if (!version) return false;
|
|
237
|
+
return compareSemver(version, newestVersion) < 0;
|
|
238
|
+
}
|
|
239
|
+
|
|
179
240
|
function isPolicyOnlySession(session) {
|
|
180
241
|
return !!(session && session.isPolicyOnly);
|
|
181
242
|
}
|
|
@@ -231,6 +292,9 @@
|
|
|
231
292
|
isLeader: false,
|
|
232
293
|
authenticated: false,
|
|
233
294
|
kind: 'policy',
|
|
295
|
+
serverVersion: '',
|
|
296
|
+
clientPlatform: '',
|
|
297
|
+
clientPlatformLabel: '',
|
|
234
298
|
isPolicyOnly: true,
|
|
235
299
|
});
|
|
236
300
|
}
|
|
@@ -254,12 +318,63 @@
|
|
|
254
318
|
// Build a key from current sessions to detect changes
|
|
255
319
|
function sessionListKey(list) {
|
|
256
320
|
return list.map(function(s) {
|
|
257
|
-
return
|
|
321
|
+
return [
|
|
322
|
+
s.sessionId,
|
|
323
|
+
s.status,
|
|
324
|
+
s.displayName || '',
|
|
325
|
+
s.serverVersion || '',
|
|
326
|
+
s.clientPlatform || '',
|
|
327
|
+
s.clientPlatformLabel || '',
|
|
328
|
+
s.isLeader ? 'leader' : 'member',
|
|
329
|
+
s.authenticated ? 'auth' : 'noauth',
|
|
330
|
+
isPolicyOnlySession(s) ? 'policy' : 'live'
|
|
331
|
+
].join(':');
|
|
258
332
|
}).join(',')
|
|
259
333
|
+ '|policyDebug:' + (showPolicySessions ? 'on' : 'off')
|
|
260
334
|
+ '|knownPolicy:' + policySessions.map(function(session) { return session.sessionId; }).join(',');
|
|
261
335
|
}
|
|
262
336
|
|
|
337
|
+
function normalizeLiveSessions(list) {
|
|
338
|
+
if (!Array.isArray(list)) return [];
|
|
339
|
+
var normalized = [];
|
|
340
|
+
var seen = new Set();
|
|
341
|
+
|
|
342
|
+
for (var i = 0; i < list.length; i++) {
|
|
343
|
+
var item = list[i];
|
|
344
|
+
if (!item || typeof item.sessionId !== 'string') continue;
|
|
345
|
+
var sessionId = nfc(item.sessionId).trim();
|
|
346
|
+
if (!sessionId || seen.has(sessionId)) continue;
|
|
347
|
+
seen.add(sessionId);
|
|
348
|
+
|
|
349
|
+
var clientPlatform = normalizeClientPlatform(item.clientPlatform);
|
|
350
|
+
var clientPlatformLabel = '';
|
|
351
|
+
if (typeof item.clientPlatformLabel === 'string' && item.clientPlatformLabel.trim()) {
|
|
352
|
+
clientPlatformLabel = nfc(item.clientPlatformLabel).trim();
|
|
353
|
+
} else if (clientPlatform) {
|
|
354
|
+
clientPlatformLabel = CLIENT_PLATFORM_LABELS[clientPlatform] || '';
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
normalized.push({
|
|
358
|
+
sessionId: sessionId,
|
|
359
|
+
displayName: nfc(typeof item.displayName === 'string' && item.displayName ? item.displayName : sessionId),
|
|
360
|
+
color: typeof item.color === 'string' ? item.color : '',
|
|
361
|
+
pid: typeof item.pid === 'number' ? item.pid : 0,
|
|
362
|
+
startedAt: typeof item.startedAt === 'string' ? item.startedAt : '',
|
|
363
|
+
lastHeartbeat: typeof item.lastHeartbeat === 'string' ? item.lastHeartbeat : '',
|
|
364
|
+
status: item.status === 'ended' ? 'ended' : 'active',
|
|
365
|
+
isLeader: !!item.isLeader,
|
|
366
|
+
authenticated: !!item.authenticated,
|
|
367
|
+
kind: typeof item.kind === 'string' ? item.kind : 'mcp',
|
|
368
|
+
serverVersion: normalizeSemver(item.serverVersion) || (typeof item.serverVersion === 'string' ? nfc(item.serverVersion).trim() : ''),
|
|
369
|
+
consoleProtocolVersion: typeof item.consoleProtocolVersion === 'number' ? item.consoleProtocolVersion : 0,
|
|
370
|
+
clientPlatform: clientPlatform,
|
|
371
|
+
clientPlatformLabel: clientPlatformLabel,
|
|
372
|
+
});
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
return normalized;
|
|
376
|
+
}
|
|
377
|
+
|
|
263
378
|
function setPolicyDebugVisibility(nextVisible, keepDropdownOpen) {
|
|
264
379
|
var normalized = !!nextVisible;
|
|
265
380
|
if (showPolicySessions === normalized) return;
|
|
@@ -513,6 +628,7 @@
|
|
|
513
628
|
if (!a.isLeader && b.isLeader) return 1;
|
|
514
629
|
return 0;
|
|
515
630
|
});
|
|
631
|
+
var newestKnownVersion = getNewestKnownSessionVersion(sorted);
|
|
516
632
|
|
|
517
633
|
function appendSessionItem(s) {
|
|
518
634
|
var item = document.createElement('div');
|
|
@@ -529,11 +645,37 @@
|
|
|
529
645
|
if (s.color) dot.style.background = s.color;
|
|
530
646
|
item.appendChild(dot);
|
|
531
647
|
|
|
648
|
+
var nameWrap = document.createElement('div');
|
|
649
|
+
nameWrap.className = 'session-dropdown-primary';
|
|
650
|
+
|
|
532
651
|
var nameEl = document.createElement('span');
|
|
533
652
|
nameEl.className = 'session-dropdown-name';
|
|
534
653
|
nameEl.textContent = displayName(s);
|
|
535
654
|
if (s.color) nameEl.style.color = s.color;
|
|
536
|
-
|
|
655
|
+
nameWrap.appendChild(nameEl);
|
|
656
|
+
|
|
657
|
+
var versionText = displayVersion(s);
|
|
658
|
+
if (versionText) {
|
|
659
|
+
var metaRow = document.createElement('div');
|
|
660
|
+
metaRow.className = 'session-dropdown-meta';
|
|
661
|
+
|
|
662
|
+
var versionEl = document.createElement('span');
|
|
663
|
+
versionEl.className = 'session-dropdown-version';
|
|
664
|
+
versionEl.textContent = versionText;
|
|
665
|
+
metaRow.appendChild(versionEl);
|
|
666
|
+
|
|
667
|
+
if (sessionHasUpdateAvailable(s, newestKnownVersion)) {
|
|
668
|
+
var updateBadge = document.createElement('span');
|
|
669
|
+
updateBadge.className = 'session-dropdown-update';
|
|
670
|
+
updateBadge.textContent = 'Update available';
|
|
671
|
+
updateBadge.title = 'A newer local DollhouseMCP session version is active.';
|
|
672
|
+
metaRow.appendChild(updateBadge);
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
nameWrap.appendChild(metaRow);
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
item.appendChild(nameWrap);
|
|
537
679
|
|
|
538
680
|
// Session status badges (#1805) — for persisted policy sessions we
|
|
539
681
|
// switch from "live/authenticated" semantics to "saved/no client".
|
|
@@ -554,6 +696,9 @@
|
|
|
554
696
|
}
|
|
555
697
|
item.appendChild(authBadge);
|
|
556
698
|
|
|
699
|
+
var clientWrap = document.createElement('div');
|
|
700
|
+
clientWrap.className = 'session-dropdown-badge-stack';
|
|
701
|
+
|
|
557
702
|
var clientBadge = document.createElement('span');
|
|
558
703
|
clientBadge.className = 'session-status-badge';
|
|
559
704
|
if (isPolicyOnlySession(s)) {
|
|
@@ -569,7 +714,17 @@
|
|
|
569
714
|
clientBadge.dataset.status = 'negative';
|
|
570
715
|
clientBadge.title = 'No MCP client attached';
|
|
571
716
|
}
|
|
572
|
-
|
|
717
|
+
clientWrap.appendChild(clientBadge);
|
|
718
|
+
|
|
719
|
+
var platformLabel = displayPlatform(s);
|
|
720
|
+
if (platformLabel) {
|
|
721
|
+
var clientLabel = document.createElement('span');
|
|
722
|
+
clientLabel.className = 'session-dropdown-client-label';
|
|
723
|
+
clientLabel.textContent = platformLabel;
|
|
724
|
+
clientWrap.appendChild(clientLabel);
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
item.appendChild(clientWrap);
|
|
573
728
|
|
|
574
729
|
var uptimeEl = document.createElement('span');
|
|
575
730
|
uptimeEl.className = 'session-dropdown-uptime';
|
|
@@ -727,7 +882,7 @@
|
|
|
727
882
|
return res.json();
|
|
728
883
|
}).then(function(data) {
|
|
729
884
|
if (data && data.sessions) {
|
|
730
|
-
sessions = data.sessions;
|
|
885
|
+
sessions = normalizeLiveSessions(data.sessions);
|
|
731
886
|
maybeForceReloadForNewLeader(sessions);
|
|
732
887
|
updateSessionIndicator();
|
|
733
888
|
updateSessionFilterOptions();
|
|
@@ -743,6 +898,7 @@
|
|
|
743
898
|
window.DollhouseSessions = {
|
|
744
899
|
getFilterSessionId: function() { return filterSessionId; },
|
|
745
900
|
displayName: displayName,
|
|
901
|
+
displayPlatform: displayPlatform,
|
|
746
902
|
getSessions: function() { return sessions; },
|
|
747
903
|
getLiveSessions: getLiveSessions,
|
|
748
904
|
getSelectableSessions: getSelectableSessions,
|
package/dist/web/public/setup.js
CHANGED
|
@@ -13,6 +13,9 @@
|
|
|
13
13
|
const PKG = '@dollhousemcp/mcp-server';
|
|
14
14
|
const HOOKS_DIR = '~/.dollhouse/hooks';
|
|
15
15
|
const HOOK_BASE_SCRIPT_PATH = `${HOOKS_DIR}/pretooluse-dollhouse.sh`;
|
|
16
|
+
const HOOK_CONTRACT_DOC_URL = 'https://github.com/DollhouseMCP/mcp-server/blob/main/docs/architecture/permission-hook-platform-contracts.md';
|
|
17
|
+
// Keep hook entrypoints and output expectations in sync with
|
|
18
|
+
// docs/architecture/permission-hook-platform-contracts.md.
|
|
16
19
|
|
|
17
20
|
/** Platform registry — drives config generation AND panel rendering */
|
|
18
21
|
const PLATFORMS = [
|
|
@@ -677,6 +680,13 @@ codex_hooks = true`;
|
|
|
677
680
|
const updatePermissionInstallButton = (btn, detected) => {
|
|
678
681
|
if (!btn || btn.classList.contains('is-success')) return;
|
|
679
682
|
|
|
683
|
+
if (detected?.hookNeedsRepair) {
|
|
684
|
+
btn.textContent = 'Repair hooks';
|
|
685
|
+
btn.disabled = false;
|
|
686
|
+
btn.classList.remove('is-match');
|
|
687
|
+
return;
|
|
688
|
+
}
|
|
689
|
+
|
|
680
690
|
if (detected?.hookInstalled) {
|
|
681
691
|
btn.textContent = 'Permissions enabled';
|
|
682
692
|
btn.disabled = true;
|
|
@@ -1116,7 +1126,30 @@ codex_hooks = true`;
|
|
|
1116
1126
|
return PERMISSION_SUPPORT_MATRIX[platformId];
|
|
1117
1127
|
};
|
|
1118
1128
|
|
|
1129
|
+
const getHookRepairStatusCopy = (support, detected) => {
|
|
1130
|
+
if (detected?.hookNeedsRepair) {
|
|
1131
|
+
return {
|
|
1132
|
+
tone: 'warning',
|
|
1133
|
+
titleText: `${support.label} hook files need repair.`,
|
|
1134
|
+
messageText: 'DollhouseMCP detected stale local hook assets. Use Configure Now below to rewrite them, or reload the local server so the automatic repair pass can run again.',
|
|
1135
|
+
};
|
|
1136
|
+
}
|
|
1137
|
+
|
|
1138
|
+
if (detected?.hookAutoRepaired) {
|
|
1139
|
+
return {
|
|
1140
|
+
tone: 'info',
|
|
1141
|
+
titleText: `${support.label} hook files were refreshed automatically.`,
|
|
1142
|
+
messageText: 'The installed local hook assets were updated to match this release. Restart the client if it is already running.',
|
|
1143
|
+
};
|
|
1144
|
+
}
|
|
1145
|
+
|
|
1146
|
+
return null;
|
|
1147
|
+
};
|
|
1148
|
+
|
|
1119
1149
|
const getFullNativePermissionStatusCopy = (support, detected) => {
|
|
1150
|
+
const repairCopy = getHookRepairStatusCopy(support, detected);
|
|
1151
|
+
if (repairCopy) return repairCopy;
|
|
1152
|
+
|
|
1120
1153
|
if (detected?.hookInstalled) {
|
|
1121
1154
|
return {
|
|
1122
1155
|
tone: 'info',
|
|
@@ -1142,6 +1175,9 @@ codex_hooks = true`;
|
|
|
1142
1175
|
|
|
1143
1176
|
const getPartialPermissionStatusCopy = (support, detected) => {
|
|
1144
1177
|
const activationLabel = support.label === 'Codex' ? 'Bash guardrails' : 'permission hooks';
|
|
1178
|
+
const repairCopy = getHookRepairStatusCopy(support, detected);
|
|
1179
|
+
if (repairCopy) return repairCopy;
|
|
1180
|
+
|
|
1145
1181
|
if (detected?.hookInstalled) {
|
|
1146
1182
|
return {
|
|
1147
1183
|
tone: 'info',
|
|
@@ -1182,6 +1218,9 @@ codex_hooks = true`;
|
|
|
1182
1218
|
};
|
|
1183
1219
|
|
|
1184
1220
|
const getManualPermissionStatusCopy = (support, detected) => {
|
|
1221
|
+
const repairCopy = getHookRepairStatusCopy(support, detected);
|
|
1222
|
+
if (repairCopy) return repairCopy;
|
|
1223
|
+
|
|
1185
1224
|
if (detected?.hookAssetsPrepared) {
|
|
1186
1225
|
return {
|
|
1187
1226
|
tone: 'info',
|
|
@@ -1591,6 +1630,7 @@ codex_hooks = true`;
|
|
|
1591
1630
|
intro.innerHTML = `<div class="setup-permissions-note">
|
|
1592
1631
|
<strong>Permissions & Security</strong>
|
|
1593
1632
|
<p>Use this mode to turn on permission enforcement for supported clients. Claude Code is fully guided in this release. Gemini CLI, Cursor, VS Code, Windsurf, and Codex have native partial support, while Cline and LM Studio stay in the MCP and fallback lane for now. Other clients will be marked as coming soon.</p>
|
|
1633
|
+
<p class="setup-hint">Need the advanced client-by-client hook contract details? <a href="${HOOK_CONTRACT_DOC_URL}" target="_blank" rel="noopener noreferrer">Read the platform contract reference</a>.</p>
|
|
1594
1634
|
</div>`;
|
|
1595
1635
|
};
|
|
1596
1636
|
|
|
@@ -14,6 +14,7 @@ import type { MCPAQLHandler } from '../../handlers/mcp-aql/MCPAQLHandler.js';
|
|
|
14
14
|
*/
|
|
15
15
|
export interface RegisterPermissionRoutesOptions {
|
|
16
16
|
homeDir?: string;
|
|
17
|
+
autoRepairHookAssets?: boolean;
|
|
17
18
|
}
|
|
18
19
|
export declare function registerPermissionRoutes(router: Router, handler: MCPAQLHandler, options?: RegisterPermissionRoutesOptions): void;
|
|
19
20
|
//# sourceMappingURL=permissionRoutes.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"permissionRoutes.d.ts","sourceRoot":"","sources":["../../../src/web/routes/permissionRoutes.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAgB,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAG1C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yCAAyC,CAAC;
|
|
1
|
+
{"version":3,"file":"permissionRoutes.d.ts","sourceRoot":"","sources":["../../../src/web/routes/permissionRoutes.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAgB,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAG1C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yCAAyC,CAAC;AAyV7E;;;GAGG;AACH,MAAM,WAAW,+BAA+B;IAC9C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC;AAED,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,aAAa,EACtB,OAAO,GAAE,+BAAoC,GAC5C,IAAI,CAiPN"}
|