@syke1/mcp-server 1.4.1 → 1.4.2
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/dist/config.d.ts +4 -0
- package/dist/config.js +23 -0
- package/dist/index.js +29 -3
- package/dist/license/validator.d.ts +4 -0
- package/dist/license/validator.js +14 -0
- package/dist/web/public/app.js +102 -0
- package/dist/web/public/index.html +19 -0
- package/dist/web/public/style.css +119 -0
- package/dist/web/server.d.ts +6 -1
- package/dist/web/server.js +16 -1
- package/package.json +1 -1
package/dist/config.d.ts
CHANGED
|
@@ -14,6 +14,10 @@ export declare function getConfig(key: keyof SykeConfig, envVar?: string): strin
|
|
|
14
14
|
* Get all resolved config (for logging/debug)
|
|
15
15
|
*/
|
|
16
16
|
export declare function getAllConfig(): Record<string, string | undefined>;
|
|
17
|
+
/**
|
|
18
|
+
* Set a config value in ~/.syke/config.json
|
|
19
|
+
*/
|
|
20
|
+
export declare function setConfig(key: keyof SykeConfig, value: string | null): void;
|
|
17
21
|
export declare const CONFIG_DIR_PATH: string;
|
|
18
22
|
export declare const CONFIG_FILE_PATH: string;
|
|
19
23
|
export {};
|
package/dist/config.js
CHANGED
|
@@ -36,6 +36,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
36
36
|
exports.CONFIG_FILE_PATH = exports.CONFIG_DIR_PATH = void 0;
|
|
37
37
|
exports.getConfig = getConfig;
|
|
38
38
|
exports.getAllConfig = getAllConfig;
|
|
39
|
+
exports.setConfig = setConfig;
|
|
39
40
|
/**
|
|
40
41
|
* Central config reader for SYKE MCP Server.
|
|
41
42
|
*
|
|
@@ -94,5 +95,27 @@ function getAllConfig() {
|
|
|
94
95
|
port: getConfig("port", "SYKE_WEB_PORT"),
|
|
95
96
|
};
|
|
96
97
|
}
|
|
98
|
+
/**
|
|
99
|
+
* Set a config value in ~/.syke/config.json
|
|
100
|
+
*/
|
|
101
|
+
function setConfig(key, value) {
|
|
102
|
+
const file = readConfigFile();
|
|
103
|
+
if (value === null) {
|
|
104
|
+
delete file[key];
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
file[key] = value;
|
|
108
|
+
}
|
|
109
|
+
try {
|
|
110
|
+
if (!fs.existsSync(CONFIG_DIR)) {
|
|
111
|
+
fs.mkdirSync(CONFIG_DIR, { recursive: true });
|
|
112
|
+
}
|
|
113
|
+
fs.writeFileSync(CONFIG_FILE, JSON.stringify(file, null, 2));
|
|
114
|
+
cached = file;
|
|
115
|
+
}
|
|
116
|
+
catch {
|
|
117
|
+
// ignore write errors
|
|
118
|
+
}
|
|
119
|
+
}
|
|
97
120
|
exports.CONFIG_DIR_PATH = CONFIG_DIR;
|
|
98
121
|
exports.CONFIG_FILE_PATH = CONFIG_FILE;
|
package/dist/index.js
CHANGED
|
@@ -121,7 +121,7 @@ async function main() {
|
|
|
121
121
|
};
|
|
122
122
|
process.on("SIGINT", shutdown);
|
|
123
123
|
process.on("SIGTERM", shutdown);
|
|
124
|
-
const server = new index_js_1.Server({ name: "syke", version: "1.4.
|
|
124
|
+
const server = new index_js_1.Server({ name: "syke", version: "1.4.2" }, { capabilities: { tools: {} } });
|
|
125
125
|
// List tools
|
|
126
126
|
server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => ({
|
|
127
127
|
tools: [
|
|
@@ -558,7 +558,33 @@ async function main() {
|
|
|
558
558
|
}
|
|
559
559
|
// Start Express web server with file cache for SSE (only if project detected)
|
|
560
560
|
if (currentProjectRoot) {
|
|
561
|
-
const { app: webApp, setFileCache: setWebFileCache } = (0, server_1.createWebServer)(() => (0, graph_1.getGraph)(currentProjectRoot, currentPackageName), fileCache, switchProject, () => currentProjectRoot, () => currentPackageName, () => licenseStatus, () => !!(0, provider_1.getAIProvider)())
|
|
561
|
+
const { app: webApp, setFileCache: setWebFileCache } = (0, server_1.createWebServer)(() => (0, graph_1.getGraph)(currentProjectRoot, currentPackageName), fileCache, switchProject, () => currentProjectRoot, () => currentPackageName, () => licenseStatus, () => !!(0, provider_1.getAIProvider)(), async (key) => {
|
|
562
|
+
// Stop existing heartbeat/session
|
|
563
|
+
await (0, validator_1.stopAndDeactivate)();
|
|
564
|
+
if (key && key.startsWith("SYKE-")) {
|
|
565
|
+
(0, config_1.setConfig)("licenseKey", key);
|
|
566
|
+
(0, validator_1.clearLicenseCache)(); // clear stale cache from previous key
|
|
567
|
+
try {
|
|
568
|
+
licenseStatus = await (0, validator_1.checkLicense)();
|
|
569
|
+
}
|
|
570
|
+
catch {
|
|
571
|
+
licenseStatus = { plan: "free", source: "default" };
|
|
572
|
+
}
|
|
573
|
+
if (licenseStatus.plan === "pro") {
|
|
574
|
+
return { success: true, plan: licenseStatus.plan, expiresAt: licenseStatus.expiresAt };
|
|
575
|
+
}
|
|
576
|
+
else {
|
|
577
|
+
return { success: false, error: licenseStatus.error || "Invalid or expired key" };
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
else {
|
|
581
|
+
// Remove key
|
|
582
|
+
(0, config_1.setConfig)("licenseKey", null);
|
|
583
|
+
(0, validator_1.clearLicenseCache)();
|
|
584
|
+
licenseStatus = { plan: "free", source: "default" };
|
|
585
|
+
return { success: true, plan: "free" };
|
|
586
|
+
}
|
|
587
|
+
});
|
|
562
588
|
webServerHandle = { setFileCache: setWebFileCache };
|
|
563
589
|
webApp.listen(WEB_PORT, () => {
|
|
564
590
|
const dashUrl = `http://localhost:${WEB_PORT}`;
|
|
@@ -587,7 +613,7 @@ main().catch((err) => {
|
|
|
587
613
|
* See: https://smithery.ai/docs/deploy#sandbox-server
|
|
588
614
|
*/
|
|
589
615
|
function createSandboxServer() {
|
|
590
|
-
const sandboxServer = new index_js_1.Server({ name: "syke", version: "1.4.
|
|
616
|
+
const sandboxServer = new index_js_1.Server({ name: "syke", version: "1.4.2" }, { capabilities: { tools: {} } });
|
|
591
617
|
sandboxServer.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => ({
|
|
592
618
|
tools: [
|
|
593
619
|
{
|
|
@@ -17,6 +17,10 @@ export declare function stopAndDeactivate(): Promise<void>;
|
|
|
17
17
|
* Get current device fingerprint (exported for use by index.ts)
|
|
18
18
|
*/
|
|
19
19
|
export declare function getDeviceId(): string;
|
|
20
|
+
/**
|
|
21
|
+
* Clear license cache file (called when license key changes)
|
|
22
|
+
*/
|
|
23
|
+
export declare function clearLicenseCache(): void;
|
|
20
24
|
/**
|
|
21
25
|
* Main license validation — called on MCP server startup
|
|
22
26
|
*/
|
|
@@ -36,6 +36,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
36
36
|
exports.startHeartbeat = startHeartbeat;
|
|
37
37
|
exports.stopAndDeactivate = stopAndDeactivate;
|
|
38
38
|
exports.getDeviceId = getDeviceId;
|
|
39
|
+
exports.clearLicenseCache = clearLicenseCache;
|
|
39
40
|
exports.checkLicense = checkLicense;
|
|
40
41
|
const fs = __importStar(require("fs"));
|
|
41
42
|
const path = __importStar(require("path"));
|
|
@@ -219,6 +220,19 @@ async function stopAndDeactivate() {
|
|
|
219
220
|
function getDeviceId() {
|
|
220
221
|
return getDeviceFingerprint();
|
|
221
222
|
}
|
|
223
|
+
/**
|
|
224
|
+
* Clear license cache file (called when license key changes)
|
|
225
|
+
*/
|
|
226
|
+
function clearLicenseCache() {
|
|
227
|
+
try {
|
|
228
|
+
if (fs.existsSync(CACHE_FILE)) {
|
|
229
|
+
fs.unlinkSync(CACHE_FILE);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
catch {
|
|
233
|
+
// silently fail
|
|
234
|
+
}
|
|
235
|
+
}
|
|
222
236
|
/**
|
|
223
237
|
* Main license validation — called on MCP server startup
|
|
224
238
|
*/
|
package/dist/web/public/app.js
CHANGED
|
@@ -463,6 +463,7 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
463
463
|
setupTabs();
|
|
464
464
|
setupSettings();
|
|
465
465
|
setupProjectModal();
|
|
466
|
+
setupLicenseModal();
|
|
466
467
|
setupFileTree();
|
|
467
468
|
initSSE();
|
|
468
469
|
startHealthCheck();
|
|
@@ -3661,6 +3662,7 @@ async function loadProjectInfo() {
|
|
|
3661
3662
|
}
|
|
3662
3663
|
hideServerOffline();
|
|
3663
3664
|
updateLicenseBadge(info.plan, info.expiresAt);
|
|
3665
|
+
updateLicenseButton(info.plan);
|
|
3664
3666
|
// Bottom bar: fetch version from npm registry
|
|
3665
3667
|
updateBottomBar();
|
|
3666
3668
|
} catch (e) {
|
|
@@ -3802,6 +3804,106 @@ async function switchProject(projectPath) {
|
|
|
3802
3804
|
}
|
|
3803
3805
|
}
|
|
3804
3806
|
|
|
3807
|
+
// ══════════════════════════════════════════════════════════════
|
|
3808
|
+
// LICENSE MODAL
|
|
3809
|
+
// ══════════════════════════════════════════════════════════════
|
|
3810
|
+
function setupLicenseModal() {
|
|
3811
|
+
const btn = document.getElementById("btn-license");
|
|
3812
|
+
const modal = document.getElementById("license-modal");
|
|
3813
|
+
const input = document.getElementById("license-key-input");
|
|
3814
|
+
const activateBtn = document.getElementById("btn-license-activate");
|
|
3815
|
+
const deactivateBtn = document.getElementById("btn-license-deactivate");
|
|
3816
|
+
const cancelBtn = document.getElementById("btn-license-cancel");
|
|
3817
|
+
const statusEl = document.getElementById("license-modal-status");
|
|
3818
|
+
if (!btn || !modal) return;
|
|
3819
|
+
|
|
3820
|
+
function openModal() {
|
|
3821
|
+
modal.classList.remove("hidden");
|
|
3822
|
+
input.value = "";
|
|
3823
|
+
statusEl.textContent = "";
|
|
3824
|
+
statusEl.className = "";
|
|
3825
|
+
input.focus();
|
|
3826
|
+
}
|
|
3827
|
+
function closeModal() {
|
|
3828
|
+
modal.classList.add("hidden");
|
|
3829
|
+
}
|
|
3830
|
+
|
|
3831
|
+
btn.addEventListener("click", openModal);
|
|
3832
|
+
cancelBtn.addEventListener("click", closeModal);
|
|
3833
|
+
modal.addEventListener("click", (e) => { if (e.target === modal) closeModal(); });
|
|
3834
|
+
|
|
3835
|
+
activateBtn.addEventListener("click", async () => {
|
|
3836
|
+
const key = input.value.trim();
|
|
3837
|
+
if (!key || !key.startsWith("SYKE-")) {
|
|
3838
|
+
statusEl.className = "error";
|
|
3839
|
+
statusEl.textContent = "Key must start with SYKE-";
|
|
3840
|
+
return;
|
|
3841
|
+
}
|
|
3842
|
+
statusEl.className = "loading";
|
|
3843
|
+
statusEl.textContent = "VALIDATING...";
|
|
3844
|
+
activateBtn.disabled = true;
|
|
3845
|
+
|
|
3846
|
+
try {
|
|
3847
|
+
const res = await fetch("/api/set-license-key", {
|
|
3848
|
+
method: "POST",
|
|
3849
|
+
headers: { "Content-Type": "application/json" },
|
|
3850
|
+
body: JSON.stringify({ key }),
|
|
3851
|
+
});
|
|
3852
|
+
const data = await res.json();
|
|
3853
|
+
if (data.success && data.plan === "pro") {
|
|
3854
|
+
statusEl.className = "success";
|
|
3855
|
+
statusEl.textContent = "PRO ACTIVATED";
|
|
3856
|
+
updateLicenseBadge("pro", data.expiresAt);
|
|
3857
|
+
updateLicenseButton("pro");
|
|
3858
|
+
setTimeout(closeModal, 1200);
|
|
3859
|
+
} else {
|
|
3860
|
+
statusEl.className = "error";
|
|
3861
|
+
statusEl.textContent = data.error || "Activation failed";
|
|
3862
|
+
}
|
|
3863
|
+
} catch (err) {
|
|
3864
|
+
statusEl.className = "error";
|
|
3865
|
+
statusEl.textContent = "Network error";
|
|
3866
|
+
}
|
|
3867
|
+
activateBtn.disabled = false;
|
|
3868
|
+
});
|
|
3869
|
+
|
|
3870
|
+
deactivateBtn.addEventListener("click", async () => {
|
|
3871
|
+
if (!confirm("Remove license key? Dashboard will switch to Free mode.")) return;
|
|
3872
|
+
statusEl.className = "loading";
|
|
3873
|
+
statusEl.textContent = "REMOVING...";
|
|
3874
|
+
|
|
3875
|
+
try {
|
|
3876
|
+
const res = await fetch("/api/set-license-key", {
|
|
3877
|
+
method: "POST",
|
|
3878
|
+
headers: { "Content-Type": "application/json" },
|
|
3879
|
+
body: JSON.stringify({ key: null }),
|
|
3880
|
+
});
|
|
3881
|
+
const data = await res.json();
|
|
3882
|
+
if (data.success) {
|
|
3883
|
+
statusEl.className = "success";
|
|
3884
|
+
statusEl.textContent = "KEY REMOVED";
|
|
3885
|
+
updateLicenseBadge("free", null);
|
|
3886
|
+
updateLicenseButton("free");
|
|
3887
|
+
setTimeout(closeModal, 800);
|
|
3888
|
+
}
|
|
3889
|
+
} catch {
|
|
3890
|
+
statusEl.className = "error";
|
|
3891
|
+
statusEl.textContent = "Failed to remove key";
|
|
3892
|
+
}
|
|
3893
|
+
});
|
|
3894
|
+
|
|
3895
|
+
input.addEventListener("keydown", (e) => {
|
|
3896
|
+
if (e.key === "Enter") activateBtn.click();
|
|
3897
|
+
if (e.key === "Escape") closeModal();
|
|
3898
|
+
});
|
|
3899
|
+
}
|
|
3900
|
+
|
|
3901
|
+
function updateLicenseButton(plan) {
|
|
3902
|
+
const btn = document.getElementById("btn-license");
|
|
3903
|
+
if (!btn) return;
|
|
3904
|
+
btn.textContent = plan === "pro" ? "LICENSED" : "LICENSE";
|
|
3905
|
+
}
|
|
3906
|
+
|
|
3805
3907
|
function setupProjectModal() {
|
|
3806
3908
|
const openBtn = document.getElementById("btn-change-project");
|
|
3807
3909
|
const modal = document.getElementById("project-modal");
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
<span class="logo-sub">CODE IMPACT RADAR</span>
|
|
21
21
|
<span id="sse-status" class="sse-indicator offline">OFFLINE</span>
|
|
22
22
|
<span id="license-badge" class="license-badge free">FREE</span>
|
|
23
|
+
<button id="btn-license" class="top-btn license-btn">LICENSE</button>
|
|
23
24
|
</div>
|
|
24
25
|
<div class="project-selector">
|
|
25
26
|
<span id="current-project" class="project-path">Loading...</span>
|
|
@@ -436,6 +437,24 @@
|
|
|
436
437
|
</div>
|
|
437
438
|
</div>
|
|
438
439
|
|
|
440
|
+
<!-- License Modal -->
|
|
441
|
+
<div id="license-modal" class="hidden">
|
|
442
|
+
<div class="license-modal-panel">
|
|
443
|
+
<h3>ACTIVATE LICENSE</h3>
|
|
444
|
+
<p class="license-modal-desc">Enter your SYKE API key to unlock Pro features.</p>
|
|
445
|
+
<div class="license-input-row">
|
|
446
|
+
<input type="text" id="license-key-input" placeholder="SYKE-XXXX-XXXX-XXXX-XXXX" spellcheck="false" autocomplete="off">
|
|
447
|
+
</div>
|
|
448
|
+
<div id="license-modal-status"></div>
|
|
449
|
+
<div class="license-modal-actions">
|
|
450
|
+
<button id="btn-license-activate">ACTIVATE</button>
|
|
451
|
+
<button id="btn-license-deactivate" class="license-deactivate-btn">REMOVE KEY</button>
|
|
452
|
+
<button id="btn-license-cancel">CANCEL</button>
|
|
453
|
+
</div>
|
|
454
|
+
<p class="license-modal-hint">Get your key at <a href="https://syke.cloud/dashboard" target="_blank">syke.cloud/dashboard</a></p>
|
|
455
|
+
</div>
|
|
456
|
+
</div>
|
|
457
|
+
|
|
439
458
|
<!-- Bottom status bar -->
|
|
440
459
|
<div id="bottom-bar">
|
|
441
460
|
<span id="bottom-info">SYKE v--- · ---</span>
|
|
@@ -1941,6 +1941,125 @@ main {
|
|
|
1941
1941
|
text-align: left;
|
|
1942
1942
|
}
|
|
1943
1943
|
|
|
1944
|
+
/* ═══════════════════════════════════════════ */
|
|
1945
|
+
/* License Modal */
|
|
1946
|
+
/* ═══════════════════════════════════════════ */
|
|
1947
|
+
#license-modal {
|
|
1948
|
+
position: fixed;
|
|
1949
|
+
inset: 0;
|
|
1950
|
+
background: rgba(5,10,24,0.85);
|
|
1951
|
+
z-index: 400;
|
|
1952
|
+
display: flex;
|
|
1953
|
+
align-items: center;
|
|
1954
|
+
justify-content: center;
|
|
1955
|
+
backdrop-filter: blur(4px);
|
|
1956
|
+
}
|
|
1957
|
+
#license-modal.hidden { display: none; }
|
|
1958
|
+
|
|
1959
|
+
.license-modal-panel {
|
|
1960
|
+
background: var(--bg-secondary);
|
|
1961
|
+
border: 1px solid var(--accent-dim);
|
|
1962
|
+
border-radius: 6px;
|
|
1963
|
+
padding: 24px 32px;
|
|
1964
|
+
min-width: 420px;
|
|
1965
|
+
max-width: 480px;
|
|
1966
|
+
box-shadow: var(--glow-cyan), 0 16px 64px rgba(0,0,0,0.5);
|
|
1967
|
+
}
|
|
1968
|
+
.license-modal-panel h3 {
|
|
1969
|
+
font-size: 12px;
|
|
1970
|
+
color: var(--accent);
|
|
1971
|
+
letter-spacing: 3px;
|
|
1972
|
+
margin-bottom: 8px;
|
|
1973
|
+
}
|
|
1974
|
+
.license-modal-desc {
|
|
1975
|
+
font-size: 11px;
|
|
1976
|
+
color: var(--text-muted);
|
|
1977
|
+
margin-bottom: 16px;
|
|
1978
|
+
}
|
|
1979
|
+
.license-input-row {
|
|
1980
|
+
margin-bottom: 12px;
|
|
1981
|
+
}
|
|
1982
|
+
.license-input-row input {
|
|
1983
|
+
width: 100%;
|
|
1984
|
+
padding: 10px 14px;
|
|
1985
|
+
background: rgba(0,0,0,0.5);
|
|
1986
|
+
border: 1px solid var(--border);
|
|
1987
|
+
border-radius: 3px;
|
|
1988
|
+
color: var(--text-primary);
|
|
1989
|
+
font-family: var(--font-mono);
|
|
1990
|
+
font-size: 13px;
|
|
1991
|
+
letter-spacing: 1.5px;
|
|
1992
|
+
outline: none;
|
|
1993
|
+
transition: border-color 0.2s;
|
|
1994
|
+
box-sizing: border-box;
|
|
1995
|
+
}
|
|
1996
|
+
.license-input-row input:focus {
|
|
1997
|
+
border-color: var(--accent);
|
|
1998
|
+
box-shadow: 0 0 8px rgba(0,212,255,0.15);
|
|
1999
|
+
}
|
|
2000
|
+
.license-input-row input::placeholder {
|
|
2001
|
+
color: var(--text-muted);
|
|
2002
|
+
letter-spacing: 2px;
|
|
2003
|
+
font-size: 11px;
|
|
2004
|
+
}
|
|
2005
|
+
#license-modal-status {
|
|
2006
|
+
min-height: 20px;
|
|
2007
|
+
font-size: 11px;
|
|
2008
|
+
margin-bottom: 12px;
|
|
2009
|
+
}
|
|
2010
|
+
#license-modal-status.success { color: var(--green); }
|
|
2011
|
+
#license-modal-status.error { color: #ff5f57; }
|
|
2012
|
+
#license-modal-status.loading { color: var(--accent); }
|
|
2013
|
+
|
|
2014
|
+
.license-modal-actions {
|
|
2015
|
+
display: flex;
|
|
2016
|
+
gap: 8px;
|
|
2017
|
+
margin-bottom: 12px;
|
|
2018
|
+
}
|
|
2019
|
+
.license-modal-actions button {
|
|
2020
|
+
padding: 8px 18px;
|
|
2021
|
+
border: 1px solid var(--accent-dim);
|
|
2022
|
+
border-radius: 3px;
|
|
2023
|
+
background: transparent;
|
|
2024
|
+
color: var(--accent);
|
|
2025
|
+
font-family: var(--font-mono);
|
|
2026
|
+
font-size: 10px;
|
|
2027
|
+
letter-spacing: 2px;
|
|
2028
|
+
cursor: pointer;
|
|
2029
|
+
transition: all 0.2s;
|
|
2030
|
+
}
|
|
2031
|
+
.license-modal-actions button:hover {
|
|
2032
|
+
background: rgba(0,212,255,0.08);
|
|
2033
|
+
border-color: var(--accent);
|
|
2034
|
+
}
|
|
2035
|
+
#btn-license-activate {
|
|
2036
|
+
background: rgba(0,212,255,0.1) !important;
|
|
2037
|
+
border-color: var(--accent) !important;
|
|
2038
|
+
font-weight: 700;
|
|
2039
|
+
}
|
|
2040
|
+
.license-deactivate-btn {
|
|
2041
|
+
color: #ff5f57 !important;
|
|
2042
|
+
border-color: rgba(255,95,87,0.3) !important;
|
|
2043
|
+
}
|
|
2044
|
+
.license-deactivate-btn:hover {
|
|
2045
|
+
background: rgba(255,95,87,0.08) !important;
|
|
2046
|
+
border-color: #ff5f57 !important;
|
|
2047
|
+
}
|
|
2048
|
+
.license-modal-hint {
|
|
2049
|
+
font-size: 10px;
|
|
2050
|
+
color: var(--text-muted);
|
|
2051
|
+
}
|
|
2052
|
+
.license-modal-hint a {
|
|
2053
|
+
color: var(--accent);
|
|
2054
|
+
text-decoration: none;
|
|
2055
|
+
}
|
|
2056
|
+
|
|
2057
|
+
.license-btn {
|
|
2058
|
+
font-size: 9px !important;
|
|
2059
|
+
padding: 2px 8px !important;
|
|
2060
|
+
letter-spacing: 1.5px;
|
|
2061
|
+
}
|
|
2062
|
+
|
|
1944
2063
|
/* ═══════════════════════════════════════════ */
|
|
1945
2064
|
/* Project Switch Modal */
|
|
1946
2065
|
/* ═══════════════════════════════════════════ */
|
package/dist/web/server.d.ts
CHANGED
|
@@ -35,4 +35,9 @@ export declare function createWebServer(getGraphFn: () => DependencyGraph, initi
|
|
|
35
35
|
expiresAt?: string;
|
|
36
36
|
error?: string;
|
|
37
37
|
source?: string;
|
|
38
|
-
}, hasAIKeyFn?: () => boolean
|
|
38
|
+
}, hasAIKeyFn?: () => boolean, setLicenseKeyFn?: (key: string | null) => Promise<{
|
|
39
|
+
success: boolean;
|
|
40
|
+
plan?: string;
|
|
41
|
+
expiresAt?: string;
|
|
42
|
+
error?: string;
|
|
43
|
+
}>): WebServerHandle;
|
package/dist/web/server.js
CHANGED
|
@@ -226,7 +226,7 @@ function acknowledgeWarnings() {
|
|
|
226
226
|
function getAllWarnings() {
|
|
227
227
|
return [...warningStore];
|
|
228
228
|
}
|
|
229
|
-
function createWebServer(getGraphFn, initialFileCache, switchProjectFn, getProjectRoot, getPackageName, getLicenseStatus, hasAIKeyFn) {
|
|
229
|
+
function createWebServer(getGraphFn, initialFileCache, switchProjectFn, getProjectRoot, getPackageName, getLicenseStatus, hasAIKeyFn, setLicenseKeyFn) {
|
|
230
230
|
const app = (0, express_1.default)();
|
|
231
231
|
app.use(express_1.default.json());
|
|
232
232
|
// Serve static files from public/
|
|
@@ -752,6 +752,21 @@ function createWebServer(getGraphFn, initialFileCache, switchProjectFn, getProje
|
|
|
752
752
|
sykeVersion,
|
|
753
753
|
});
|
|
754
754
|
});
|
|
755
|
+
// POST /api/set-license-key — Set or remove license key via dashboard
|
|
756
|
+
app.post("/api/set-license-key", async (req, res) => {
|
|
757
|
+
if (!setLicenseKeyFn) {
|
|
758
|
+
res.status(501).json({ success: false, error: "Not supported" });
|
|
759
|
+
return;
|
|
760
|
+
}
|
|
761
|
+
const { key } = req.body;
|
|
762
|
+
try {
|
|
763
|
+
const result = await setLicenseKeyFn(key || null);
|
|
764
|
+
res.json(result);
|
|
765
|
+
}
|
|
766
|
+
catch (err) {
|
|
767
|
+
res.status(500).json({ success: false, error: err.message || "Unknown error" });
|
|
768
|
+
}
|
|
769
|
+
});
|
|
755
770
|
// GET /api/browse-dirs — List subdirectories for folder browser
|
|
756
771
|
app.get("/api/browse-dirs", (req, res) => {
|
|
757
772
|
const dirPath = req.query.path || (process.platform === "win32" ? "C:\\" : "/");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@syke1/mcp-server",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.2",
|
|
4
4
|
"mcpName": "io.github.khalomsky/syke",
|
|
5
5
|
"description": "AI code impact analysis MCP server — dependency graphs, cascade detection, and a mandatory build gate for AI coding agents",
|
|
6
6
|
"main": "dist/index.js",
|