clay-server 4.8.2 → 5.0.0-beta.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/LICENSES/README.md +13 -0
- package/LICENSES/open-iconic.txt +21 -0
- package/LICENSES/plantuml-salt.txt +674 -0
- package/lib/assets/salt-assets.json +15 -0
- package/lib/assets/salt-colors.json +156 -0
- package/lib/assets/salt-font-10.bin.gz +0 -0
- package/lib/assets/salt-font-13.bin.gz +0 -0
- package/lib/assets/salt-font-14.bin.gz +0 -0
- package/lib/assets/salt-font-16.bin.gz +0 -0
- package/lib/assets/salt-font-18.bin.gz +0 -0
- package/lib/assets/salt-font-20.bin.gz +0 -0
- package/lib/assets/salt-font-metrics.bin.gz +0 -0
- package/lib/assets/salt-font-metrics.json +101 -0
- package/lib/assets/salt-font-monospace-10.bin.gz +0 -0
- package/lib/assets/salt-font-monospace-13.bin.gz +0 -0
- package/lib/assets/salt-font-monospace-14.bin.gz +0 -0
- package/lib/assets/salt-font-monospace-16.bin.gz +0 -0
- package/lib/assets/salt-font-monospace-18.bin.gz +0 -0
- package/lib/assets/salt-font-monospace-20.bin.gz +0 -0
- package/lib/assets/salt-font-monospace.bin.gz +0 -0
- package/lib/assets/salt-icons.json +671 -0
- package/lib/bundled-skills/clay-sketch/SKILL.md +198 -0
- package/lib/mcp-browser-proxy.js +37 -0
- package/lib/mcp-connection-store.js +39 -0
- package/lib/mcp-network.js +46 -0
- package/lib/mcp-oauth.js +65 -0
- package/lib/mcp-proxy.js +32 -0
- package/lib/mcp-remote-connections.js +215 -0
- package/lib/mcp-session-access.js +15 -0
- package/lib/plantuml-renderer.js +43 -0
- package/lib/project-file-http.js +2 -0
- package/lib/project-mcp.js +130 -357
- package/lib/project-plantuml.js +48 -0
- package/lib/project-session-document.js +17 -1
- package/lib/project-user-message.js +2 -0
- package/lib/project-wireframe-http.js +88 -0
- package/lib/project.js +28 -45
- package/lib/public/app.js +7 -0
- package/lib/public/css/filebrowser.css +5 -0
- package/lib/public/css/mcp-connections.css +86 -0
- package/lib/public/css/skills-workbench.css +74 -0
- package/lib/public/css/wireframe.css +95 -0
- package/lib/public/index.html +16 -15
- package/lib/public/modules/app-messages.js +10 -2
- package/lib/public/modules/filebrowser.js +29 -3
- package/lib/public/modules/markdown.js +3 -1
- package/lib/public/modules/mcp-connection-view.js +136 -0
- package/lib/public/modules/mcp-permissions.js +122 -0
- package/lib/public/modules/mcp-ui.js +85 -461
- package/lib/public/modules/plantuml-preview.js +76 -0
- package/lib/public/modules/skills-actions.js +47 -79
- package/lib/public/modules/skills-detail.js +32 -145
- package/lib/public/modules/skills-list-view.js +29 -0
- package/lib/public/modules/skills-state.js +4 -2
- package/lib/public/modules/skills.js +104 -399
- package/lib/public/modules/split-view.js +14 -0
- package/lib/public/modules/vendor-login-browser.js +16 -5
- package/lib/public/modules/wireframe-chat.js +52 -0
- package/lib/public/modules/wireframe-render.js +69 -0
- package/lib/public/modules/wireframe-style.js +6 -0
- package/lib/public/modules/wireframe-viewport.js +70 -0
- package/lib/public/modules/wireframe-workbench.js +116 -0
- package/lib/public/style.css +3 -0
- package/lib/salt-chrome.js +36 -0
- package/lib/salt-hand.js +37 -0
- package/lib/salt-images.js +87 -0
- package/lib/salt-layout.js +60 -0
- package/lib/salt-options.js +23 -0
- package/lib/salt-overlays.js +45 -0
- package/lib/salt-parser.js +153 -0
- package/lib/salt-screen.js +111 -0
- package/lib/salt-svg-shapes.js +80 -0
- package/lib/salt-svg.js +164 -0
- package/lib/salt-text.js +112 -0
- package/lib/salt-tree.js +45 -0
- package/lib/sdk-bridge.js +5 -17
- package/lib/sdk-mcp-descriptors.js +2 -1
- package/lib/session-document-mcp-server.js +9 -0
- package/lib/vendor-login-browser-worker.js +18 -8
- package/lib/vendor-login-browser.js +10 -3
- package/lib/yoke/adapters/codex.js +1 -18
- package/package.json +6 -2
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
var fs = require('fs');
|
|
2
|
+
var path = require('path');
|
|
3
|
+
var renderer = require('./plantuml-renderer');
|
|
4
|
+
var filePaths = require('./project-file-path');
|
|
5
|
+
|
|
6
|
+
function error(status, message) { return Object.assign(new Error(message), { status: status }); }
|
|
7
|
+
function readBody(req) {
|
|
8
|
+
return new Promise(function (resolve, reject) {
|
|
9
|
+
var chunks = [];
|
|
10
|
+
var size = 0;
|
|
11
|
+
req.on('data', function (chunk) {
|
|
12
|
+
size += Buffer.byteLength(chunk);
|
|
13
|
+
if (size > 650000) { chunks = []; reject(error(413, 'Diagram request is too large.')); return; }
|
|
14
|
+
chunks.push(chunk);
|
|
15
|
+
});
|
|
16
|
+
req.on('aborted', function () { reject(error(400, 'Request cancelled.')); });
|
|
17
|
+
req.on('error', reject);
|
|
18
|
+
req.on('end', function () {
|
|
19
|
+
if (size > 650000) return;
|
|
20
|
+
try { resolve(JSON.parse(Buffer.concat(chunks).toString('utf8'))); }
|
|
21
|
+
catch (e) { reject(error(400, 'Invalid diagram request.')); }
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function attachWireframeHTTP(ctx) {
|
|
27
|
+
function projectAccess(req) {
|
|
28
|
+
if (!ctx.requestAccess.canAccessProject(req, ctx.slug)) throw error(403, 'Project access is not permitted.');
|
|
29
|
+
}
|
|
30
|
+
function save(req, body, source) {
|
|
31
|
+
var scope = ctx.requestAccess.fileScope(req);
|
|
32
|
+
var requested = body.path;
|
|
33
|
+
if (typeof requested !== 'string' || !/\.puml$/i.test(requested) || requested.indexOf('\0') !== -1 || path.isAbsolute(requested)) {
|
|
34
|
+
throw error(400, 'Choose a project-relative .puml path.');
|
|
35
|
+
}
|
|
36
|
+
var root = fs.realpathSync(ctx.cwd);
|
|
37
|
+
var target = path.resolve(root, requested);
|
|
38
|
+
var parent = filePaths.resolveFilePath(root, path.dirname(target), { projectBound: true });
|
|
39
|
+
target = path.join(parent, path.basename(target));
|
|
40
|
+
try {
|
|
41
|
+
if (scope.identity) ctx.fsAsUser('write', { file: target, content: source, flag: 'wx' }, scope.identity);
|
|
42
|
+
else fs.writeFileSync(target, source, { encoding: 'utf8', flag: 'wx' });
|
|
43
|
+
} catch (e) {
|
|
44
|
+
if (e.code === 'EEXIST' || /EEXIST/.test(String(e.stderr || ''))) throw error(409, 'A file already exists at this path. Choose a new name.');
|
|
45
|
+
throw e;
|
|
46
|
+
}
|
|
47
|
+
return path.relative(root, target).split(path.sep).join('/');
|
|
48
|
+
}
|
|
49
|
+
function handleHTTP(req, res, urlPath) {
|
|
50
|
+
if (urlPath !== '/api/wireframe/render' && urlPath !== '/api/wireframe/save') return false;
|
|
51
|
+
function fail(e) {
|
|
52
|
+
if (res.destroyed || res.writableEnded) return;
|
|
53
|
+
var mapped = filePaths.fileError(e);
|
|
54
|
+
res.writeHead(e.status || mapped.status, { 'Content-Type': 'text/plain; charset=utf-8', 'Cache-Control': 'no-store' });
|
|
55
|
+
res.end(e.status ? e.message : mapped.message);
|
|
56
|
+
}
|
|
57
|
+
try {
|
|
58
|
+
projectAccess(req);
|
|
59
|
+
if (req.method !== 'POST') throw error(405, 'Use POST for wireframes.');
|
|
60
|
+
if (!/^application\/json\b/i.test(req.headers['content-type'] || '') || req.headers['sec-fetch-site'] === 'cross-site') throw error(415, 'Use a same-origin JSON request.');
|
|
61
|
+
} catch (e) { fail(e); return true; }
|
|
62
|
+
var controller = new AbortController();
|
|
63
|
+
function cancel() { controller.abort(); }
|
|
64
|
+
res.once('close', cancel);
|
|
65
|
+
readBody(req).then(function (body) {
|
|
66
|
+
if (controller.signal.aborted) return;
|
|
67
|
+
projectAccess(req);
|
|
68
|
+
if (!body || typeof body.source !== 'string') throw error(400, 'Diagram source is required.');
|
|
69
|
+
var source = renderer.prepareSource(body.source, body.language === 'salt' ? 'diagram.salt' : 'diagram.puml');
|
|
70
|
+
if (urlPath === '/api/wireframe/save') {
|
|
71
|
+
var saved = save(req, body, source);
|
|
72
|
+
res.writeHead(201, { 'Content-Type': 'application/json', 'Cache-Control': 'no-store' });
|
|
73
|
+
res.end(JSON.stringify({ path: saved }));
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
return (ctx.renderPlantUml || renderer.renderPlantUml)(source, { signal: controller.signal }).then(function (svg) {
|
|
77
|
+
if (controller.signal.aborted) return;
|
|
78
|
+
projectAccess(req);
|
|
79
|
+
res.writeHead(200, { 'Content-Type': 'image/svg+xml; charset=utf-8', 'Cache-Control': 'no-store',
|
|
80
|
+
'X-Content-Type-Options': 'nosniff', 'Content-Security-Policy': "default-src 'none'; style-src 'unsafe-inline'; sandbox" });
|
|
81
|
+
res.end(svg);
|
|
82
|
+
});
|
|
83
|
+
}).catch(fail).finally(function () { res.removeListener('close', cancel); });
|
|
84
|
+
return true;
|
|
85
|
+
}
|
|
86
|
+
return { handleHTTP: handleHTTP };
|
|
87
|
+
}
|
|
88
|
+
module.exports = { attachWireframeHTTP: attachWireframeHTTP };
|
package/lib/project.js
CHANGED
|
@@ -47,7 +47,6 @@ var { attachConnection } = require("./project-connection");
|
|
|
47
47
|
var { attachProjectScheduledMessages } = require("./project-scheduled-messages");
|
|
48
48
|
var { attachMcp } = require("./project-mcp");
|
|
49
49
|
var { createSessionSkillCatalog } = require("./yoke/session-skill-catalog");
|
|
50
|
-
var { createLocalMcp } = require("./mcp-local");
|
|
51
50
|
var { attachEmail: attachEmailModule } = require("./project-email");
|
|
52
51
|
var { attachSessionSpawn } = require("./project-session-spawn");
|
|
53
52
|
var { attachDelegatedSession } = require("./project-delegated-session");
|
|
@@ -696,27 +695,30 @@ function createProjectContext(opts) {
|
|
|
696
695
|
sm.defaultModelByVendor = sm.defaultModelByVendor || {};
|
|
697
696
|
if (savedDefaultModel) sm.defaultModelByVendor[sm.defaultVendor || "claude"] = savedDefaultModel;
|
|
698
697
|
|
|
699
|
-
//
|
|
700
|
-
var _localMcp = createLocalMcp();
|
|
701
|
-
|
|
702
|
-
// --- MCP bridge (remote MCP servers via Chrome Extension) ---
|
|
698
|
+
// Personal computer tools use the extension; remote URLs are owner-bound.
|
|
703
699
|
var _mcp = attachMcp({
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
return
|
|
712
|
-
? opts.onGetProjectMcpServers(slug) : [];
|
|
700
|
+
sendTo: sendTo, slug: slug, clients: clients,
|
|
701
|
+
root: require("./config").CONFIG_DIR,
|
|
702
|
+
isMultiUser: function () { return usersModule.isMultiUser(); },
|
|
703
|
+
canAccess: function (ws) { return _requestAccess.canAccessProject(ws, slug); },
|
|
704
|
+
canUseOwner: function (owner) {
|
|
705
|
+
if (!usersModule.isMultiUser()) return owner === "default";
|
|
706
|
+
var user = usersModule.findUserById(owner);
|
|
707
|
+
return !!user && _requestAccess.canAccessProject({ _clayUser: user }, slug);
|
|
713
708
|
},
|
|
714
|
-
|
|
715
|
-
if (
|
|
716
|
-
|
|
717
|
-
|
|
709
|
+
canUseSession: function (session) {
|
|
710
|
+
if (!session || sm.sessions.get(session.localId) !== session) return false;
|
|
711
|
+
if (!usersModule.isMultiUser()) return true;
|
|
712
|
+
if (!require("./mcp-session-access").canUsePersonalConnections(session, sm.sessions)) return false;
|
|
713
|
+
var user = session.ownerId && usersModule.findUserById(session.ownerId);
|
|
714
|
+
return !!user && _requestAccess.canAccessProject({ _clayUser: user }, slug) &&
|
|
715
|
+
usersModule.canAccessSession(user.id, session, opts.getProjectAccess ? opts.getProjectAccess() : { visibility: "public" });
|
|
716
|
+
},
|
|
717
|
+
identity: function (ws) { return _requestAccess.osIdentity(ws); },
|
|
718
|
+
extensionId: function (ws) { return ws._clayMcpExtensionId || null; },
|
|
719
|
+
getEnabledMcpServers: function () {
|
|
720
|
+
return typeof opts.onGetProjectMcpServers === "function" ? opts.onGetProjectMcpServers(slug) : [];
|
|
718
721
|
},
|
|
719
|
-
localMcp: _localMcp,
|
|
720
722
|
});
|
|
721
723
|
|
|
722
724
|
// --- Email module (delegated to project-email.js) ---
|
|
@@ -1372,7 +1374,7 @@ function createProjectContext(opts) {
|
|
|
1372
1374
|
osUsers: osUsers,
|
|
1373
1375
|
dangerouslySkipPermissions: dangerouslySkipPermissions,
|
|
1374
1376
|
mcpServers: getLocalMcpServers,
|
|
1375
|
-
getRemoteMcpServers: function () { return _mcp.getMcpServers(); },
|
|
1377
|
+
getRemoteMcpServers: function (session) { return _mcp.getMcpServers(session); },
|
|
1376
1378
|
clayPort: serverPort,
|
|
1377
1379
|
clayTls: serverTls,
|
|
1378
1380
|
clayAuthToken: serverAuthToken,
|
|
@@ -1706,14 +1708,6 @@ function createProjectContext(opts) {
|
|
|
1706
1708
|
// --- WS connection handler (delegated to project-connection.js) ---
|
|
1707
1709
|
function handleConnection(ws, wsUser) {
|
|
1708
1710
|
_connection.handleConnection(ws, wsUser, handleMessage, handleDisconnection);
|
|
1709
|
-
|
|
1710
|
-
// Initialize local MCP when a localhost client connects
|
|
1711
|
-
if (ws._clayLocal && _localMcp && !_localMcp.isReady()) {
|
|
1712
|
-
_localMcp.initialize(function () {
|
|
1713
|
-
// Rebuild proxy servers and broadcast state when local servers are ready
|
|
1714
|
-
_mcp.rebuildAndBroadcast();
|
|
1715
|
-
});
|
|
1716
|
-
}
|
|
1717
1711
|
}
|
|
1718
1712
|
|
|
1719
1713
|
// --- WS message handler ---
|
|
@@ -2028,6 +2022,7 @@ function createProjectContext(opts) {
|
|
|
2028
2022
|
|
|
2029
2023
|
// --- WS disconnection handler (delegated to project-connection.js) ---
|
|
2030
2024
|
function handleDisconnection(ws) {
|
|
2025
|
+
_mcp.handleExtensionDisconnect(ws);
|
|
2031
2026
|
// Clean up extension WS reference if this was the extension client
|
|
2032
2027
|
if (browserState._extensionWs === ws) {
|
|
2033
2028
|
browserState._extensionWs = null;
|
|
@@ -2316,17 +2311,6 @@ function createProjectContext(opts) {
|
|
|
2316
2311
|
&& sm.sessions.get(boundSession.localId) === boundSession
|
|
2317
2312
|
&& Number(boundSession._sdkQueryGeneration || 0) === queryGeneration;
|
|
2318
2313
|
}
|
|
2319
|
-
// Build set of local MCP server names to exclude (Codex handles these natively)
|
|
2320
|
-
var localMcpNames = {};
|
|
2321
|
-
try {
|
|
2322
|
-
var mcpLocalModule = require("./mcp-local");
|
|
2323
|
-
var localConfig = mcpLocalModule.readMergedServers();
|
|
2324
|
-
var lcNames = Object.keys(localConfig);
|
|
2325
|
-
for (var li = 0; li < lcNames.length; li++) {
|
|
2326
|
-
localMcpNames[lcNames[li]] = true;
|
|
2327
|
-
}
|
|
2328
|
-
} catch (e) { /* no local MCP config */ }
|
|
2329
|
-
|
|
2330
2314
|
return {
|
|
2331
2315
|
listTools: function () {
|
|
2332
2316
|
var tools = [];
|
|
@@ -2352,7 +2336,7 @@ function createProjectContext(opts) {
|
|
|
2352
2336
|
var toolNames = Object.keys(server.instance._registeredTools);
|
|
2353
2337
|
for (var j = 0; j < toolNames.length; j++) {
|
|
2354
2338
|
var toolDef = server.instance._registeredTools[toolNames[j]];
|
|
2355
|
-
var inputSchema = normalizeToolSchema(toolDef.inputSchema);
|
|
2339
|
+
var inputSchema = toolDef._clayInputSchema || normalizeToolSchema(toolDef.inputSchema);
|
|
2356
2340
|
tools.push({
|
|
2357
2341
|
server: serverName,
|
|
2358
2342
|
name: toolNames[j],
|
|
@@ -2459,13 +2443,11 @@ function createProjectContext(opts) {
|
|
|
2459
2443
|
}
|
|
2460
2444
|
}
|
|
2461
2445
|
|
|
2462
|
-
//
|
|
2463
|
-
var remoteServers = _mcp.getMcpServers();
|
|
2446
|
+
// Personal computer and remote URL connections.
|
|
2447
|
+
var remoteServers = _mcp.getMcpServers(boundSession);
|
|
2464
2448
|
if (remoteServers) {
|
|
2465
2449
|
var remoteNames = Object.keys(remoteServers);
|
|
2466
2450
|
for (var ri = 0; ri < remoteNames.length; ri++) {
|
|
2467
|
-
// Skip servers that Codex manages natively via Track 1
|
|
2468
|
-
if (localMcpNames[remoteNames[ri]]) continue;
|
|
2469
2451
|
extractServerTools(remoteNames[ri], remoteServers[remoteNames[ri]]);
|
|
2470
2452
|
}
|
|
2471
2453
|
}
|
|
@@ -2571,7 +2553,7 @@ function createProjectContext(opts) {
|
|
|
2571
2553
|
}
|
|
2572
2554
|
}
|
|
2573
2555
|
// Try remote/local proxy servers
|
|
2574
|
-
var remoteServers = _mcp.getMcpServers();
|
|
2556
|
+
var remoteServers = _mcp.getMcpServers(boundSession);
|
|
2575
2557
|
if (remoteServers && remoteServers[serverName]) {
|
|
2576
2558
|
var rServer = remoteServers[serverName];
|
|
2577
2559
|
if (rServer.instance && rServer.instance._registeredTools && rServer.instance._registeredTools[toolName]) {
|
|
@@ -2673,6 +2655,7 @@ function createProjectContext(opts) {
|
|
|
2673
2655
|
|
|
2674
2656
|
// --- Destroy ---
|
|
2675
2657
|
function destroy() {
|
|
2658
|
+
_mcp.destroy();
|
|
2676
2659
|
_sharedBrowser.destroy();
|
|
2677
2660
|
_vendorLogin.destroy();
|
|
2678
2661
|
if (_scheduledMessages) _scheduledMessages.shutdown();
|
package/lib/public/app.js
CHANGED
|
@@ -273,6 +273,7 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
|
|
|
273
273
|
sharedBrowser: null,
|
|
274
274
|
sharedBrowsers: [],
|
|
275
275
|
mcpSkillsWorkbench: {},
|
|
276
|
+
mcpConnections: { screen: "list", servers: [], search: "", loaded: false },
|
|
276
277
|
sharedBrowserOpen: false,
|
|
277
278
|
sharedBrowserUi: {},
|
|
278
279
|
// session / routing
|
|
@@ -360,6 +361,12 @@ import { initDebate, handleDebatePreparing, handleDebateStarted, handleDebateRes
|
|
|
360
361
|
savedMainSlug: null,
|
|
361
362
|
connected: false,
|
|
362
363
|
fileReadRequest: null,
|
|
364
|
+
fileViewerIsPlantUml: false,
|
|
365
|
+
plantUmlPreviewJob: null,
|
|
366
|
+
wireframeDraft: null,
|
|
367
|
+
wireframeRenderQueue: [],
|
|
368
|
+
wireframeRenderActive: null,
|
|
369
|
+
wireframeRenderCache: [],
|
|
363
370
|
pendingFileNavigation: null,
|
|
364
371
|
rightWorkbenchOwner: null,
|
|
365
372
|
rightWorkbenchRevision: 0,
|
|
@@ -2629,3 +2629,8 @@
|
|
|
2629
2629
|
animation: message-blink 0.5s ease 3;
|
|
2630
2630
|
border-radius: 12px;
|
|
2631
2631
|
}
|
|
2632
|
+
|
|
2633
|
+
/* PlantUML is rendered locally and displayed as an inert, scalable image. */
|
|
2634
|
+
.file-viewer-plantuml-preview { padding: 20px; min-height: 100%; box-sizing: border-box; }
|
|
2635
|
+
.file-viewer-plantuml-preview img { display: block; max-width: 100%; height: auto; margin: 0 auto; background: #fff; border-radius: 4px; }
|
|
2636
|
+
.file-viewer-plantuml-preview [role="status"]:empty { display: none; }
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/* Personal connections share the existing workbench's typography and theme. */
|
|
2
|
+
#mcp-skills-workbench .ext-pill-wrap[hidden] { display:none; }
|
|
3
|
+
.mc-screen { max-width:640px; margin:0 auto; padding:4px 4px 24px; font-size:13px; color:var(--text); }
|
|
4
|
+
.mc-screen button,.mc-screen input,.mc-screen select { font:inherit; }
|
|
5
|
+
.mc-screen button { cursor:pointer; }
|
|
6
|
+
.mc-screen button:disabled { opacity:.5; cursor:wait; }
|
|
7
|
+
.mc-screen svg { width:16px; height:16px; flex-shrink:0; }
|
|
8
|
+
.mc-heading { margin:16px 0 28px; }
|
|
9
|
+
.mc-heading h2 { font-size:22px; font-weight:600; letter-spacing:-.5px; margin:12px 0 8px; overflow-wrap:anywhere; }
|
|
10
|
+
.mc-heading p,.mc-muted,.mc-footnote { color:var(--text-muted); line-height:1.7; margin:0; }
|
|
11
|
+
.mc-emblem { display:inline-flex; padding:12px; background:var(--bg-alt); border:1px solid var(--border); border-radius:12px; }
|
|
12
|
+
.mc-emblem svg { width:24px; height:24px; }
|
|
13
|
+
.mc-button { display:inline-flex; align-items:center; justify-content:center; gap:7px; padding:9px 13px; border:1px solid var(--border); border-radius:8px; background:var(--bg); color:var(--text); line-height:1.4; }
|
|
14
|
+
.mc-button:hover { background:var(--bg-alt); }
|
|
15
|
+
.mc-primary { background:var(--accent); border-color:var(--accent); color:var(--bg); font-weight:600; }
|
|
16
|
+
.mc-primary:hover { background:var(--accent); filter:brightness(.95); }
|
|
17
|
+
.mc-back { display:inline-flex; align-items:center; gap:7px; padding:4px 0; background:none; border:0; color:var(--text-muted); }
|
|
18
|
+
.mc-back:hover { color:var(--text); }
|
|
19
|
+
.mc-empty { display:flex; flex-direction:column; align-items:center; text-align:center; padding:64px 18px; }
|
|
20
|
+
.mc-empty .mc-heading { margin-bottom:24px; }
|
|
21
|
+
.mc-empty>p { max-width:260px; color:var(--text-muted); line-height:1.7; margin-top:18px; font-size:12px; }
|
|
22
|
+
.mc-search { display:flex; align-items:center; gap:8px; border:1px solid var(--border); background:var(--bg-alt); border-radius:8px; padding:0 10px; color:var(--text-muted); }
|
|
23
|
+
.mc-search input { width:100%; min-width:0; background:transparent; border:0; padding:10px 0; color:var(--text); outline:none; }
|
|
24
|
+
.mc-search:focus-within { outline:2px solid var(--accent); outline-offset:2px; }
|
|
25
|
+
.mc-section-heading { display:flex; align-items:center; justify-content:space-between; gap:12px; margin:24px 0 8px; }
|
|
26
|
+
.mc-section-heading h2 { font-size:13px; font-weight:600; margin:0; }
|
|
27
|
+
.mc-row { display:flex; align-items:center; gap:14px; border-bottom:1px solid var(--border); padding:16px 0; }
|
|
28
|
+
.mc-row-open { display:flex; align-items:flex-start; gap:12px; flex:1; min-width:0; text-align:left; color:var(--text); border:0; background:none; padding:0; border-radius:6px; }
|
|
29
|
+
.mc-server-icon { display:flex; border:1px solid var(--border); border-radius:9px; padding:9px; color:var(--text-muted); }
|
|
30
|
+
.mc-row-info { display:flex; flex-direction:column; gap:5px; min-width:0; }
|
|
31
|
+
.mc-row-info strong { overflow-wrap:anywhere; font-size:14px; font-weight:550; }
|
|
32
|
+
.mc-row-info>span { font-size:11px; color:var(--text-muted); }
|
|
33
|
+
.mc-status { display:inline-flex; align-items:center; gap:6px; font-size:12px; color:var(--text-muted); }
|
|
34
|
+
.mc-status>span { width:6px; height:6px; border-radius:50%; background:var(--text-muted); }
|
|
35
|
+
.mc-status[data-status="ready"]>span { background:var(--success,#55a881); }
|
|
36
|
+
.mc-status[data-status="auth_required"]>span,.mc-status[data-status="unavailable"]>span { background:#c28c42; }
|
|
37
|
+
.mc-switch { flex-shrink:0; width:32px; height:19px; padding:2px; border:1px solid var(--border); border-radius:12px; background:var(--bg-alt); }
|
|
38
|
+
.mc-switch>span { display:block; height:13px; width:13px; border-radius:50%; background:var(--text-muted); transition:transform .15s; }
|
|
39
|
+
.mc-switch[aria-checked="true"] { background:var(--accent); border-color:var(--accent); }
|
|
40
|
+
.mc-switch[aria-checked="true"]>span { background:var(--bg); transform:translateX(13px); }
|
|
41
|
+
.mc-footnote { margin-top:22px; font-size:11px; }
|
|
42
|
+
.mc-choices { display:flex; flex-direction:column; gap:12px; }
|
|
43
|
+
.mc-choice { display:flex; align-items:center; gap:14px; padding:20px 16px; text-align:left; background:var(--bg); color:var(--text); border:1px solid var(--border); border-radius:12px; }
|
|
44
|
+
.mc-choice:hover { background:var(--bg-alt); border-color:var(--text-muted); }
|
|
45
|
+
.mc-choice>span:nth-child(2) { flex:1; }
|
|
46
|
+
.mc-choice strong { display:block; margin-bottom:6px; font-size:14px; }
|
|
47
|
+
.mc-choice small { display:block; color:var(--text-muted); line-height:1.6; font-size:12px; }
|
|
48
|
+
.mc-choice-icon { display:flex; padding:10px; background:var(--bg-alt); border-radius:9px; }
|
|
49
|
+
.mc-form { display:flex; flex-direction:column; gap:16px; }
|
|
50
|
+
.mc-form label,.mc-permissions label { display:flex; flex-direction:column; gap:8px; font-weight:500; }
|
|
51
|
+
.mc-form input,.mc-permissions select { width:100%; min-width:0; box-sizing:border-box; padding:11px 12px; border:1px solid var(--border); border-radius:8px; background:var(--bg); color:var(--text); }
|
|
52
|
+
.mc-form>.mc-button { align-self:flex-end; margin-top:4px; }
|
|
53
|
+
.mc-enable { display:flex; justify-content:space-between; align-items:center; gap:12px; padding:20px 0; margin-top:8px; border-bottom:1px solid var(--border); }
|
|
54
|
+
.mc-metadata { display:grid; grid-template-columns:70px minmax(0,1fr); gap:12px; padding:8px 0; font-size:12px; }
|
|
55
|
+
.mc-metadata dt { color:var(--text-muted); }
|
|
56
|
+
.mc-metadata dd { margin:0; overflow-wrap:anywhere; }
|
|
57
|
+
.mc-alert { display:flex; align-items:flex-start; gap:10px; border:1px solid var(--border); border-left:3px solid #c28c42; background:var(--bg-alt); border-radius:8px; padding:12px; line-height:1.6; margin:12px 0; }
|
|
58
|
+
.mc-alert svg { margin-top:3px; }
|
|
59
|
+
.mc-notice { color:var(--text-muted); line-height:1.6; padding:12px; background:var(--bg-alt); border-radius:8px; }
|
|
60
|
+
.mc-auth { margin:20px 0; }
|
|
61
|
+
.mc-auth p { font-size:11px; margin-top:8px; }
|
|
62
|
+
.mc-token,.mc-manage { margin:20px 0; }
|
|
63
|
+
.mc-token summary,.mc-manage summary { color:var(--text-muted); cursor:pointer; font-size:12px; }
|
|
64
|
+
.mc-token form,.mc-manage form { margin:16px 0; }
|
|
65
|
+
.mc-detail-tabs { display:flex; gap:20px; border-bottom:1px solid var(--border); margin:26px 0 18px; }
|
|
66
|
+
.mc-detail-tabs button { color:var(--text-muted); background:none; border:0; border-bottom:2px solid transparent; padding:10px 0; }
|
|
67
|
+
.mc-detail-tabs button[aria-selected="true"] { color:var(--text); border-bottom-color:var(--accent); }
|
|
68
|
+
.mc-tools details { border-bottom:1px solid var(--border); padding:14px 0; }
|
|
69
|
+
.mc-tools summary { cursor:pointer; overflow-wrap:anywhere; }
|
|
70
|
+
.mc-tools p,.mc-permissions p { line-height:1.7; color:var(--text-muted); white-space:pre-wrap; overflow-wrap:anywhere; }
|
|
71
|
+
.mc-tools pre { padding:12px; border-radius:8px; background:var(--bg-alt); overflow:auto; max-height:240px; font-size:11px; }
|
|
72
|
+
.mc-tools h4 { font-size:11px; color:var(--text-muted); }
|
|
73
|
+
.mc-detail-actions { display:flex; flex-wrap:wrap; gap:8px; margin-top:24px; }
|
|
74
|
+
.mc-steps { list-style:none; padding:0; margin:0 0 24px; }
|
|
75
|
+
.mc-steps li { display:flex; gap:12px; padding:0 0 26px; }
|
|
76
|
+
.mc-step-marker { width:24px; height:24px; display:flex; align-items:center; justify-content:center; flex-shrink:0; border:1px solid var(--border); border-radius:50%; font-size:11px; }
|
|
77
|
+
.mc-steps li>div { min-width:0; flex:1; }
|
|
78
|
+
.mc-steps strong { font-weight:550; line-height:24px; }
|
|
79
|
+
.mc-steps p { color:var(--text-muted); line-height:1.7; margin:6px 0 12px; }
|
|
80
|
+
.mc-command { border:1px solid var(--border); border-radius:8px; padding:10px; background:var(--bg-alt); }
|
|
81
|
+
.mc-command code { display:block; white-space:pre-wrap; overflow-wrap:anywhere; margin-bottom:8px; font-size:11px; }
|
|
82
|
+
.mc-working { display:flex; gap:8px; align-items:center; color:var(--text-muted); font-size:12px; margin-top:16px; }
|
|
83
|
+
.mc-working svg { animation:mc-spin 1s linear infinite; }
|
|
84
|
+
@keyframes mc-spin { to { transform:rotate(360deg); } }
|
|
85
|
+
@media (prefers-reduced-motion:reduce) { .mc-working svg { animation:none; } .mc-switch>span { transition:none; } }
|
|
86
|
+
@media (max-width:480px) { .mc-screen { padding:0 0 20px; } .mc-empty { padding:40px 12px; } .mc-heading h2 { font-size:21px; } }
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/* A compact library inside the existing workbench. */
|
|
2
|
+
#mcp-skills-workbench #skills-modal [hidden] { display:none; }
|
|
3
|
+
#mcp-skills-workbench #skills-modal .skills-header { padding:24px 20px 16px; }
|
|
4
|
+
.skills-library-heading h2 { margin:0 0 7px; font-size:22px; letter-spacing:-.5px; font-weight:600; color:var(--text); }
|
|
5
|
+
.skills-library-heading p { margin:0; font-size:12px; color:var(--text-muted); line-height:1.6; }
|
|
6
|
+
#mcp-skills-workbench #skills-modal .skills-back-btn { gap:7px; font-size:12px; padding:0; color:var(--text-muted); background:none; border:0; }
|
|
7
|
+
#mcp-skills-workbench #skills-modal .skills-tabs { margin:0 20px; padding:0; gap:24px; border-bottom:1px solid var(--border); }
|
|
8
|
+
#mcp-skills-workbench #skills-modal .skills-tab { padding:10px 0; font-size:12px; }
|
|
9
|
+
#mcp-skills-workbench #skills-modal .skills-tab.active { color:var(--text); }
|
|
10
|
+
#skills-installed-count { margin-left:5px; color:var(--text-muted); font-size:10px; }
|
|
11
|
+
.skills-toolbar { display:flex; gap:10px; align-items:center; padding:16px 20px 0; }
|
|
12
|
+
#mcp-skills-workbench #skills-modal .skills-search { flex:1; min-width:0; margin:0; padding:9px 10px; border-radius:8px; background:var(--bg-alt); }
|
|
13
|
+
#mcp-skills-workbench #skills-modal .skills-search input { min-width:0; width:100%; font-size:12px; }
|
|
14
|
+
.skills-discovery-views { display:flex; gap:6px; flex-wrap:wrap; padding:12px 20px 0; }
|
|
15
|
+
.skills-discovery-views button { padding:7px 10px; border:1px solid transparent; border-radius:6px; background:none; color:var(--text-muted); font:inherit; font-size:11px; cursor:pointer; }
|
|
16
|
+
.skills-discovery-views button:hover { background:var(--bg-alt); color:var(--text); }
|
|
17
|
+
.skills-discovery-views button[aria-pressed="true"] { background:var(--bg-alt); border-color:var(--border); color:var(--text); }
|
|
18
|
+
.skills-discovery-views button:focus-visible { outline:2px solid var(--accent); outline-offset:2px; }
|
|
19
|
+
#mcp-skills-workbench #skills-modal .skills-content { padding:20px; }
|
|
20
|
+
.skills-list-intro { display:flex; justify-content:space-between; gap:12px; color:var(--text-muted); font-size:11px; margin-bottom:6px; }
|
|
21
|
+
.skills-library-row { display:flex; align-items:flex-start; width:100%; gap:12px; padding:17px 0; text-align:left; background:none; border:0; border-bottom:1px solid var(--border); color:var(--text); font:inherit; cursor:pointer; border-radius:4px; }
|
|
22
|
+
.skills-library-row:hover { background:var(--bg-alt); }
|
|
23
|
+
.skills-library-icon,.skills-detail-icon { display:inline-flex; padding:9px; border:1px solid var(--border); border-radius:9px; color:var(--text-muted); flex-shrink:0; }
|
|
24
|
+
.skills-library-icon svg { width:16px; height:16px; }
|
|
25
|
+
.skills-library-info { display:flex; flex-direction:column; gap:6px; flex:1; min-width:0; }
|
|
26
|
+
.skills-library-name { font-size:13px; font-weight:550; overflow-wrap:anywhere; }
|
|
27
|
+
.skills-library-desc { font-size:12px; line-height:1.65; color:var(--text-muted); display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden; }
|
|
28
|
+
.skills-library-meta { font-size:10px; color:var(--text-dimmer); overflow-wrap:anywhere; }
|
|
29
|
+
.skills-library-end { display:flex; align-items:center; gap:8px; flex-shrink:0; padding-top:3px; color:var(--text-muted); }
|
|
30
|
+
.skills-library-end>svg { width:14px; height:14px; }
|
|
31
|
+
.skills-library-badge { font-size:10px; color:var(--text-muted); }
|
|
32
|
+
.skills-library-installs { display:flex; gap:4px; align-items:center; font-size:10px; }
|
|
33
|
+
.skills-library-installs svg { width:12px; height:12px; }
|
|
34
|
+
.skills-library-empty { padding:48px 16px; text-align:center; color:var(--text-muted); }
|
|
35
|
+
.skills-library-empty>svg { width:28px; height:28px; margin-bottom:12px; }
|
|
36
|
+
.skills-library-empty h3 { color:var(--text); font-size:17px; font-weight:550; }
|
|
37
|
+
.skills-library-empty p { font-size:12px; line-height:1.7; max-width:300px; margin:12px auto; }
|
|
38
|
+
.skills-browse-btn { display:inline-flex; align-items:center; justify-content:center; gap:8px; margin-top:10px; padding:10px 14px; border:1px solid var(--border); border-radius:8px; background:var(--bg-alt); color:var(--text); font:inherit; font-size:12px; cursor:pointer; }
|
|
39
|
+
.skills-browse-btn svg { width:14px; height:14px; }
|
|
40
|
+
.skills-catalog-credit { margin:22px 0 0; font-size:11px; color:var(--text-dimmer); }
|
|
41
|
+
.skills-catalog-credit a,.skills-metadata a { color:var(--text-muted); }
|
|
42
|
+
#mcp-skills-workbench #skills-modal .skills-detail { display:flex; flex-direction:column; gap:24px; max-width:780px; margin:auto; }
|
|
43
|
+
.skills-detail-icon svg { width:22px; height:22px; }
|
|
44
|
+
#mcp-skills-workbench #skills-modal .skills-detail-name { margin:14px 0 10px; font-size:23px; letter-spacing:-.5px; font-weight:600; }
|
|
45
|
+
#mcp-skills-workbench #skills-modal .skills-detail-desc { margin:0; font-size:13px; line-height:1.8; color:var(--text-muted); }
|
|
46
|
+
.skills-detail-byline { display:flex; flex-wrap:wrap; gap:12px; margin-top:14px; font-size:11px; color:var(--text-dimmer); overflow-wrap:anywhere; }
|
|
47
|
+
.skills-placement { border:1px solid var(--border); border-radius:10px; padding:16px; background:var(--bg-alt); }
|
|
48
|
+
.skills-placement h3 { margin:0 0 7px; font-size:13px; font-weight:550; color:var(--text); }
|
|
49
|
+
.skills-placement-heading>p { font-size:11px; line-height:1.7; color:var(--text-muted); margin:0 0 16px; }
|
|
50
|
+
.skills-placement .skills-install-actions { display:flex; flex-wrap:wrap; flex-direction:row; gap:8px; }
|
|
51
|
+
.skills-placement .skills-install-btn { width:auto; flex:1; min-width:150px; border-radius:7px; padding:10px 12px; font-size:12px; }
|
|
52
|
+
.skills-placement .skills-installed-row { width:100%; gap:10px; margin-bottom:8px; flex-wrap:wrap; }
|
|
53
|
+
.skills-placement .skills-uninstall-btn,.skills-cancel-remove { width:auto; height:auto; padding:6px 9px; font:inherit; font-size:11px; color:var(--text-muted); border:1px solid var(--border); border-radius:6px; background:none; cursor:pointer; }
|
|
54
|
+
.skills-placement .skills-installed-status { flex:1; width:auto; font-size:12px; font-weight:500; padding:0; background:none; border:0; justify-content:flex-start; }
|
|
55
|
+
.skills-placement .skills-installed-status svg { width:15px; height:15px; }
|
|
56
|
+
.skills-removed-status { font-size:12px; color:var(--text-muted); }
|
|
57
|
+
#mcp-skills-workbench #skills-modal .skills-detail-md-wrap { flex:none; overflow:visible; padding:0; }
|
|
58
|
+
.skills-detail-section-title { font-size:11px; font-weight:550; letter-spacing:.04em; color:var(--text-muted); margin:0 0 16px; }
|
|
59
|
+
.skills-detail-md { overflow-wrap:anywhere; min-width:0; }
|
|
60
|
+
.skills-detail-md pre { max-width:100%; overflow:auto; }
|
|
61
|
+
.skills-detail-md table { display:block; overflow:auto; }
|
|
62
|
+
.skills-metadata,.skills-manual { border-top:1px solid var(--border); padding-top:16px; }
|
|
63
|
+
.skills-metadata summary,.skills-manual summary { cursor:pointer; font-size:12px; color:var(--text-muted); }
|
|
64
|
+
.skills-metadata dl { display:grid; grid-template-columns:90px minmax(0,1fr); gap:12px; font-size:11px; line-height:1.7; }
|
|
65
|
+
.skills-metadata dt { color:var(--text-muted); }
|
|
66
|
+
.skills-metadata dd { margin:0; overflow-wrap:anywhere; }
|
|
67
|
+
.skills-manual .skills-detail-cmd { margin:12px 0 0; }
|
|
68
|
+
.skills-local-note { display:flex; gap:10px; align-items:flex-start; color:var(--text-muted); }
|
|
69
|
+
.skills-local-note svg { width:16px; height:16px; flex-shrink:0; margin-top:3px; }
|
|
70
|
+
.skills-local-note p { margin:0; font-size:12px; line-height:1.7; }
|
|
71
|
+
@media(max-width:480px) { .skills-toolbar { flex-wrap:wrap; }.skills-library-icon { padding:7px; }.skills-library-row { gap:9px; }.skills-library-badge { max-width:48px; }.skills-library-end { gap:3px; } }
|
|
72
|
+
|
|
73
|
+
.skills-library-row:focus-visible,.skills-browse-btn:focus-visible { outline:2px solid var(--accent); outline-offset:3px; }
|
|
74
|
+
.skills-search:focus-within { box-shadow:0 0 0 1px var(--accent); }
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
.wireframe-card { margin: 16px 0; border: 1px solid var(--border); border-radius: 10px; overflow: hidden; background: var(--bg); }
|
|
2
|
+
.wireframe-card header { display: flex; align-items: center; gap: 12px; padding: 10px 14px; border-bottom: 1px solid var(--border-subtle); }
|
|
3
|
+
.wireframe-card header strong { flex: 1; font-size: 12px; color: var(--text-secondary); }
|
|
4
|
+
.wireframe-card button, #wireframe-panel button { font: inherit; font-size: 12px; border: 1px solid var(--border); border-radius: 6px; padding: 6px 9px; background: var(--bg-alt); color: var(--text); cursor: pointer; }
|
|
5
|
+
.wireframe-card button:hover, #wireframe-panel button:hover { background: var(--bg-hover); }
|
|
6
|
+
.wireframe-card :focus-visible, #wireframe-panel :focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
|
|
7
|
+
.wireframe-canvas { padding: 16px; overflow: auto; }
|
|
8
|
+
.wireframe-canvas img, .wireframe-workbench-canvas img { display: block; max-width: 100%; height: auto; margin: 0 auto; background: white; border-radius: 4px; }
|
|
9
|
+
.wireframe-card details { border-top: 1px solid var(--border-subtle); }
|
|
10
|
+
.wireframe-card summary { padding: 8px 14px; font-size: 12px; color: var(--text-muted); cursor: pointer; }
|
|
11
|
+
.wireframe-card details pre { margin: 0; border-radius: 0; }
|
|
12
|
+
#wireframe-panel { position: relative; width: 50%; max-width: 720px; min-width: 360px; height: calc(100% - 16px); min-height: 0; margin: 8px 8px 8px 10px; align-self: center; flex-shrink: 0; display: flex; flex-direction: column; overflow: hidden; background: var(--bg); color: var(--text); border: 1px solid var(--border); border-radius: 12px; }
|
|
13
|
+
.wireframe-topbar { display: flex; align-items: center; gap: 8px; height: 48px; padding: 0 12px; flex-shrink: 0; border-bottom: 1px solid var(--border-subtle); }
|
|
14
|
+
.wireframe-topbar strong { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; font-size: 13px; }
|
|
15
|
+
#wireframe-panel .lucide { width: 15px; height: 15px; flex-shrink: 0; }
|
|
16
|
+
.wireframe-window-actions { display: flex; gap: 4px; margin-left: auto; }
|
|
17
|
+
#wireframe-panel .wireframe-window-actions button { display: flex; align-items: center; justify-content: center; width: 30px; height: 30px; padding: 0; }
|
|
18
|
+
.wireframe-toolbar { display: flex; align-items: center; gap: 8px; padding: 10px 12px; border-bottom: 1px solid var(--border-subtle); }
|
|
19
|
+
.wireframe-toolbar span { flex: 1; font-size: 11px; color: var(--text-muted); }
|
|
20
|
+
.wireframe-workbench-canvas { flex: 1; min-height: 0; overflow: auto; padding: 20px; }
|
|
21
|
+
.wireframe-workbench-canvas p, .wireframe-canvas p { color: var(--text-muted); font-size: 12px; overflow-wrap: anywhere; }
|
|
22
|
+
.wireframe-save-form { padding: 12px; display: flex; flex-wrap: wrap; align-items: end; gap: 8px; background: var(--bg-alt); }
|
|
23
|
+
.wireframe-save-form[hidden] { display: none; }
|
|
24
|
+
.wireframe-save-form label { flex: 1; min-width: 140px; font-size: 12px; }
|
|
25
|
+
.wireframe-save-form input { display: block; width: 100%; box-sizing: border-box; background: var(--bg); color: var(--text); border: 1px solid var(--border); border-radius: 5px; padding: 8px; margin-top: 5px; font: inherit; }
|
|
26
|
+
.wireframe-save-status { margin: 0; padding: 8px 12px; font-size: 12px; overflow-wrap: anywhere; }
|
|
27
|
+
.wireframe-save-status:empty { display: none; }
|
|
28
|
+
#wireframe-panel button:disabled { opacity: .5; cursor: wait; }
|
|
29
|
+
@media (min-width: 1024px) {
|
|
30
|
+
#wireframe-panel { box-shadow: 4px 8px 18px rgba(var(--shadow-rgb), .14), 2px 2px 4px rgba(var(--shadow-rgb), .08), inset 0 1px 0 rgba(255,255,255,.04); animation: workbench-panel-in .18s cubic-bezier(.2,.8,.2,1); }
|
|
31
|
+
#wireframe-panel.wireframe-wide { width: 70%; max-width: 1200px; }
|
|
32
|
+
#wireframe-panel.panel-fullscreen { width: 100%; max-width: none; min-width: 0; height: 100%; margin: 0; border: 0; border-radius: 0; box-shadow: none; animation: none; }
|
|
33
|
+
}
|
|
34
|
+
@media (max-width: 1023px) {
|
|
35
|
+
#wireframe-panel { position: fixed; inset: 0; width: 100%; max-width: none; min-width: 0; height: 100%; margin: 0; border: 0; border-radius: 0; z-index: 210; padding-top: env(safe-area-inset-top); padding-bottom: env(safe-area-inset-bottom); box-sizing: border-box; }
|
|
36
|
+
#wireframe-panel .wireframe-window-actions [data-wide], #wireframe-panel .wireframe-window-actions [data-full] { display: none; }
|
|
37
|
+
}
|
|
38
|
+
@media (prefers-reduced-motion: reduce) { #wireframe-panel { animation: none; } }
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
.wireframe-toolbar { flex-wrap: wrap; }
|
|
43
|
+
.wireframe-zoom { display: flex; align-items: center; gap: 4px; flex-shrink: 0; }
|
|
44
|
+
.wireframe-zoom button { font: inherit; font-size: 12px; border: 1px solid var(--border); border-radius: 6px; padding: 6px 9px; background: var(--bg-alt); color: var(--text); cursor: pointer; }
|
|
45
|
+
.wireframe-zoom [data-zoom-value] { min-width: 55px; font-variant-numeric: tabular-nums; }
|
|
46
|
+
.wireframe-zoom [aria-pressed="true"] { background: var(--bg-hover); }
|
|
47
|
+
.wireframe-zoom button:disabled, #wireframe-panel .wireframe-zoom button:disabled { opacity: .4; cursor: default; }
|
|
48
|
+
.wireframe-file-canvas { overflow: auto; min-width: 0; padding-top: 16px; }
|
|
49
|
+
.file-viewer-plantuml-preview > .wireframe-zoom { position: sticky; top: 0; z-index: 1; width: fit-content; padding: 6px; background: var(--bg); border: 1px solid var(--border); border-radius: 8px; }
|
|
50
|
+
@media (max-width: 700px) { .wireframe-toolbar > span { flex-basis: 100%; } }
|
|
51
|
+
|
|
52
|
+
/* Shared sketch identity stays inside the existing right-panel shell. */
|
|
53
|
+
.wireframe-card, #wireframe-panel, .file-viewer-plantuml-preview { --sketch-accent: #c98b64; }
|
|
54
|
+
.wireframe-card { border-radius: 14px; border-top: 2px solid var(--sketch-accent); }
|
|
55
|
+
.sketch-brand { display: flex; align-items: center; gap: 9px; flex-shrink: 0; }
|
|
56
|
+
.wireframe-card header .sketch-brand { flex: 1; }
|
|
57
|
+
.sketch-mark { display: grid; place-items: center; width: 28px; height: 28px; border: 1px solid var(--sketch-accent); border-radius: 8px 8px 8px 2px; color: var(--sketch-accent); font-size: 23px; line-height: 1; }
|
|
58
|
+
.sketch-wordmark { font-size: 14px; font-weight: 700; letter-spacing: -.4px; color: var(--text); }
|
|
59
|
+
.sketch-wordmark > span { margin-left: 3px; font-weight: 400; color: var(--sketch-accent); }
|
|
60
|
+
.sketch-tools { display: flex; flex-wrap: wrap; align-items: center; gap: 10px; padding: 8px 14px; border-bottom: 1px solid var(--border-subtle); }
|
|
61
|
+
.sketch-credit { font-size: 11px; color: var(--text-muted); text-decoration: none; }
|
|
62
|
+
.sketch-credit:hover { color: var(--text); text-decoration: underline; }
|
|
63
|
+
.sketch-footer { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px; padding: 10px 14px; border-top: 1px solid var(--border-subtle); }
|
|
64
|
+
.sketch-footer > span { font-size: 11px; color: var(--text-muted); }
|
|
65
|
+
.wireframe-topbar { height: 56px; gap: 14px; border-top: 2px solid var(--sketch-accent); }
|
|
66
|
+
.wireframe-topbar .sketch-title { min-width: 0; color: var(--text-secondary); font-size: 12px; font-weight: 400; }
|
|
67
|
+
.wireframe-canvas, .wireframe-workbench-canvas, .wireframe-file-canvas { background-image: radial-gradient(circle, var(--border) .7px, transparent .8px); background-size: 16px 16px; }
|
|
68
|
+
.wireframe-canvas img, .wireframe-workbench-canvas img, .wireframe-file-canvas img { box-shadow: 0 2px 10px rgba(0,0,0,.1); }
|
|
69
|
+
.sketch-tools :focus-visible, .sketch-footer :focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
|
|
70
|
+
@media (max-width: 480px) {
|
|
71
|
+
.wireframe-topbar { gap: 8px; }
|
|
72
|
+
.wireframe-topbar .sketch-title { display: none; }
|
|
73
|
+
.sketch-footer > span { flex-basis: 100%; }
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/* Keep drawing controls together and give the canvas the available space. */
|
|
77
|
+
.wireframe-card header { gap: 8px; padding: 8px 12px; flex-wrap: wrap; }
|
|
78
|
+
.wireframe-card .sketch-mark { width: 22px; height: 22px; font-size: 19px; }
|
|
79
|
+
.wireframe-card header button { padding: 5px 8px; }
|
|
80
|
+
.wireframe-canvas { padding: 12px; }
|
|
81
|
+
.sketch-source-footer { position: relative; border-top: 1px solid var(--border-subtle); }
|
|
82
|
+
.sketch-source-footer details { border: 0; }
|
|
83
|
+
.sketch-source-footer summary { padding: 8px 175px 8px 12px; }
|
|
84
|
+
.sketch-source-footer > div { position: absolute; top: 7px; right: 12px; }
|
|
85
|
+
.wireframe-card .sketch-credit { font-size: 10px; color: var(--text-muted); }
|
|
86
|
+
.wireframe-topbar { height: 44px; }
|
|
87
|
+
.wireframe-toolbar { padding: 6px 10px; gap: 6px; }
|
|
88
|
+
.wireframe-workbench-canvas { padding: 12px; }
|
|
89
|
+
.sketch-footer { padding: 6px 12px; }
|
|
90
|
+
@media (max-width: 480px) {
|
|
91
|
+
.wireframe-card header { gap: 6px; }
|
|
92
|
+
.wireframe-card .sketch-brand { gap: 5px; }
|
|
93
|
+
.wireframe-card .sketch-wordmark { font-size: 12px; }
|
|
94
|
+
.wireframe-card header button { font-size: 11px; padding: 6px; }
|
|
95
|
+
}
|
package/lib/public/index.html
CHANGED
|
@@ -1733,23 +1733,24 @@
|
|
|
1733
1733
|
<div class="confirm-backdrop"></div>
|
|
1734
1734
|
<div class="confirm-dialog skills-dialog">
|
|
1735
1735
|
<div class="skills-header">
|
|
1736
|
-
<
|
|
1737
|
-
<
|
|
1738
|
-
|
|
1739
|
-
|
|
1736
|
+
<div class="skills-library-heading"><h2>Your skills</h2><p>Reusable instructions for the way you work.</p></div>
|
|
1737
|
+
<button class="skills-back-btn hidden" id="skills-back-btn" aria-label="Back to skills"><i data-lucide="arrow-left"></i><span>Skills</span></button>
|
|
1738
|
+
</div>
|
|
1739
|
+
<div class="skills-tabs" role="tablist" aria-label="Skill library">
|
|
1740
|
+
<button class="skills-tab active" role="tab" aria-selected="true" data-tab="installed">Installed <span id="skills-installed-count"></span></button>
|
|
1741
|
+
<button class="skills-tab" role="tab" aria-selected="false" tabindex="-1" data-tab="discover">Discover</button>
|
|
1742
|
+
</div>
|
|
1743
|
+
<div class="skills-toolbar">
|
|
1744
|
+
<div class="skills-search" id="skills-search">
|
|
1745
|
+
<i data-lucide="search"></i>
|
|
1746
|
+
<input type="search" id="skills-search-input" placeholder="Search installed skills" aria-label="Search installed skills" spellcheck="false" />
|
|
1747
|
+
<button class="skills-search-clear hidden" id="skills-search-clear" aria-label="Clear skill search"><i data-lucide="x"></i></button>
|
|
1740
1748
|
</div>
|
|
1741
1749
|
</div>
|
|
1742
|
-
<div class="skills-
|
|
1743
|
-
<
|
|
1744
|
-
<
|
|
1745
|
-
<
|
|
1746
|
-
<button class="skills-search-clear hidden" id="skills-search-clear"><i data-lucide="x"></i></button>
|
|
1747
|
-
</div>
|
|
1748
|
-
<div class="skills-tabs">
|
|
1749
|
-
<button class="skills-tab active" data-tab="all">All Time</button>
|
|
1750
|
-
<button class="skills-tab" data-tab="trending">Trending</button>
|
|
1751
|
-
<button class="skills-tab" data-tab="hot">Hot</button>
|
|
1752
|
-
<button class="skills-tab" data-tab="installed">Installed</button>
|
|
1750
|
+
<div class="skills-discovery-views" role="group" aria-label="Discover skills by" hidden>
|
|
1751
|
+
<button type="button" data-discovery="all" aria-pressed="true">Most installed</button>
|
|
1752
|
+
<button type="button" data-discovery="trending" aria-pressed="false">Trending</button>
|
|
1753
|
+
<button type="button" data-discovery="hot" aria-pressed="false">Growing fast</button>
|
|
1753
1754
|
</div>
|
|
1754
1755
|
<div class="skills-content" id="skills-content">
|
|
1755
1756
|
<div class="skills-loading"><div class="skills-spinner"></div> Loading skills...</div>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { handleLinearResult } from './linear-panel.js';
|
|
2
2
|
import { handleSharedBrowserMessage } from './shared-browser.js';
|
|
3
|
+
import { openWireframe } from './wireframe-workbench.js';
|
|
3
4
|
import { syncGithubSessions } from './session-github.js';
|
|
4
5
|
import { handleIssuesMessageInContext as handleIssuesMessage } from './issues-context.js';
|
|
5
6
|
// app-messages.js - WebSocket message router
|
|
@@ -60,7 +61,7 @@ import { showRewindModal, onRewindComplete, setRewindMode, onRewindError, clearP
|
|
|
60
61
|
import { checkAdminAccess } from './admin.js';
|
|
61
62
|
import { mateAvatarUrl } from './avatar.js';
|
|
62
63
|
import { showImageModal, sendExtensionCommand, handleMcpToolCallMessage } from './app-misc.js';
|
|
63
|
-
import { handleMcpServersState, handleMcpPermissionModeResult } from './mcp-ui.js';
|
|
64
|
+
import { handleMcpServersState, handleMcpPermissionModeResult, handleMcpConnectionMessage } from './mcp-ui.js';
|
|
64
65
|
import { handlePermissionModeResult } from './permission-control.js';
|
|
65
66
|
import { handleShellCommandResult } from './shell-command.js';
|
|
66
67
|
import { handleLoopRegistryUpdated, handleScheduleRunStarted, handleScheduleRunFinished, handleLoopScheduled, isSchedulerOpen, enterCraftingMode, exitCraftingMode, handleLoopRegistryFiles } from './scheduler.js';
|
|
@@ -106,6 +107,7 @@ var connectOverlay = document.getElementById("connect-overlay");
|
|
|
106
107
|
initMessageDeliveryUi();
|
|
107
108
|
|
|
108
109
|
export function processMessage(msg) {
|
|
110
|
+
if (handleMcpConnectionMessage(msg)) return;
|
|
109
111
|
if (handleSharedBrowserMessage(msg)) return;
|
|
110
112
|
if (msg.type === "vendor_login_browser_frame" || msg.type === "vendor_login_browser_status") {
|
|
111
113
|
handleLoginBrowserMessage(msg);
|
|
@@ -1148,7 +1150,7 @@ export function processMessage(msg) {
|
|
|
1148
1150
|
getTools()[msg.id] = { el: null, name: msg.name, input: null, done: true, hidden: true };
|
|
1149
1151
|
} else if (msg.name === "ask_user_questions") {
|
|
1150
1152
|
getTools()[msg.id] = { el: null, name: msg.name, input: null, done: true, hidden: true };
|
|
1151
|
-
} else if (msg.name === "present_markdown_edit" || (msg.name && msg.name.indexOf("present_markdown_edit") !== -1)) {
|
|
1153
|
+
} else if (msg.name === "present_wireframe" || (msg.name && msg.name.endsWith("__present_wireframe")) || msg.name === "present_markdown_edit" || (msg.name && msg.name.indexOf("present_markdown_edit") !== -1)) {
|
|
1152
1154
|
getTools()[msg.id] = { el: null, name: msg.name, input: null, done: true, hidden: true };
|
|
1153
1155
|
} else if (getTodoTools()[msg.name]) {
|
|
1154
1156
|
getTools()[msg.id] = { el: null, name: msg.name, input: null, done: true, hidden: true };
|
|
@@ -1584,6 +1586,12 @@ export function processMessage(msg) {
|
|
|
1584
1586
|
handleFileChanged(msg);
|
|
1585
1587
|
break;
|
|
1586
1588
|
|
|
1589
|
+
case "wireframe_present":
|
|
1590
|
+
if (!store.get('replayingHistory') && !store.get('dmMode') && (!msg.sessionId || msg.sessionId === store.get('activeSessionId'))) {
|
|
1591
|
+
if (store.get('paneMode') || !store.get('splitPanes')) openWireframe(msg);
|
|
1592
|
+
}
|
|
1593
|
+
break;
|
|
1594
|
+
|
|
1587
1595
|
case "markdown_edit_present":
|
|
1588
1596
|
if (!store.get('replayingHistory') && !store.get('dmMode')) {
|
|
1589
1597
|
if (store.get('paneMode')) forwardPaneMarkdownPresentation(msg);
|