@syke1/mcp-server 1.4.3 → 1.4.4

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/index.js CHANGED
@@ -75,12 +75,15 @@ function resolveFilePath(fileArg, projectRoot, sourceDir) {
75
75
  let licenseStatus = { plan: "free", source: "default" };
76
76
  // Free tier limits
77
77
  const FREE_MAX_FILES = 50;
78
+ function isPro() {
79
+ return isPro() || licenseStatus.plan === "pro_trial";
80
+ }
78
81
  /**
79
82
  * Check if a resolved file path is within the free tier limit.
80
83
  * Free set = first 50 files sorted alphabetically by relative path.
81
84
  */
82
85
  function isFileInFreeSet(resolvedPath, graph) {
83
- if (licenseStatus.plan === "pro")
86
+ if (isPro())
84
87
  return true;
85
88
  const allFiles = [...graph.files].sort();
86
89
  const idx = allFiles.indexOf(resolvedPath);
@@ -357,7 +360,7 @@ async function main() {
357
360
  }
358
361
  case "get_hub_files": {
359
362
  // Pro-only feature
360
- if (licenseStatus.plan !== "pro") {
363
+ if (!isPro()) {
361
364
  return {
362
365
  content: [{ type: "text", text: getProToolError("get_hub_files") }],
363
366
  };
@@ -392,7 +395,7 @@ async function main() {
392
395
  case "ai_analyze": {
393
396
  // BYOK: allow if user has their own AI key, even on Free plan
394
397
  const hasAIKey = !!(0, provider_1.getAIProvider)();
395
- if (licenseStatus.plan !== "pro" && !hasAIKey) {
398
+ if (!isPro() && !hasAIKey) {
396
399
  return {
397
400
  content: [{ type: "text", text: getProToolError("ai_analyze") + "\n\nOr set GEMINI_KEY / OPENAI_KEY / ANTHROPIC_KEY to use ai_analyze with your own API key." }],
398
401
  };
@@ -417,7 +420,7 @@ async function main() {
417
420
  const aiResult = await (0, analyzer_1.analyzeWithAI)(resolved, impactResult, graph);
418
421
  // Free tier: append partial analysis warning
419
422
  let resultText = aiResult;
420
- if (licenseStatus.plan !== "pro" && graph.files.size > FREE_MAX_FILES) {
423
+ if (!isPro() && graph.files.size > FREE_MAX_FILES) {
421
424
  resultText += `\n\n---\n⚠️ Free tier: analyzing ${FREE_MAX_FILES}/${graph.files.size} files. Some dependencies may be missing. Upgrade to Pro for full analysis: https://syke.cloud/dashboard/`;
422
425
  }
423
426
  return {
@@ -426,7 +429,7 @@ async function main() {
426
429
  }
427
430
  case "check_warnings": {
428
431
  // Pro-only feature (real-time monitoring)
429
- if (licenseStatus.plan !== "pro") {
432
+ if (!isPro()) {
430
433
  return {
431
434
  content: [{ type: "text", text: getProToolError("check_warnings") }],
432
435
  };
@@ -498,7 +501,7 @@ async function main() {
498
501
  else {
499
502
  console.error(`[syke] AI: disabled (set GEMINI_KEY, OPENAI_KEY, or ANTHROPIC_KEY)`);
500
503
  }
501
- if (licenseStatus.plan === "pro") {
504
+ if (isPro()) {
502
505
  console.error(`[syke] Pro activated for: ${licenseStatus.email || "unknown"}`);
503
506
  }
504
507
  else {
@@ -570,7 +573,7 @@ async function main() {
570
573
  catch {
571
574
  licenseStatus = { plan: "free", source: "default" };
572
575
  }
573
- if (licenseStatus.plan === "pro") {
576
+ if (isPro()) {
574
577
  return { success: true, plan: licenseStatus.plan, expiresAt: licenseStatus.expiresAt };
575
578
  }
576
579
  else {
@@ -1,5 +1,5 @@
1
1
  export interface LicenseStatus {
2
- plan: "free" | "pro";
2
+ plan: "free" | "pro" | "pro_trial";
3
3
  email?: string;
4
4
  expiresAt?: string;
5
5
  source: "online" | "cache" | "default";
@@ -170,6 +170,7 @@ async function sendHeartbeat() {
170
170
  await postJSON(HEARTBEAT_URL, {
171
171
  key: currentLicenseKey,
172
172
  deviceId: currentDeviceId,
173
+ deviceName: getDeviceName(),
173
174
  });
174
175
  }
175
176
  catch {
@@ -248,8 +249,9 @@ async function checkLicense() {
248
249
  if (cache && cache.valid && (now - cache.cachedAt) < CACHE_MAX_AGE) {
249
250
  // Cache is fresh — still start heartbeat with cached session
250
251
  startHeartbeat(key, getDeviceFingerprint());
252
+ const cachedPlan = cache.plan === "pro_trial" ? "pro_trial" : "pro";
251
253
  return {
252
- plan: "pro",
254
+ plan: cachedPlan,
253
255
  email: cache.email,
254
256
  expiresAt: cache.expiresAt,
255
257
  source: "cache",
@@ -272,8 +274,9 @@ async function checkLicense() {
272
274
  });
273
275
  // Start heartbeat
274
276
  startHeartbeat(key, getDeviceFingerprint());
277
+ const onlinePlan = result.plan === "pro_trial" ? "pro_trial" : "pro";
275
278
  return {
276
- plan: "pro",
279
+ plan: onlinePlan,
277
280
  email: result.email,
278
281
  expiresAt: result.expiresAt,
279
282
  source: "online",
@@ -290,8 +293,9 @@ async function checkLicense() {
290
293
  // Online validation failed — check if we have a grace-period cache
291
294
  if (cache && cache.valid && (now - cache.cachedAt) < CACHE_GRACE_PERIOD) {
292
295
  startHeartbeat(key, getDeviceFingerprint());
296
+ const gracePlan = cache.plan === "pro_trial" ? "pro_trial" : "pro";
293
297
  return {
294
- plan: "pro",
298
+ plan: gracePlan,
295
299
  email: cache.email,
296
300
  expiresAt: cache.expiresAt,
297
301
  source: "cache",
@@ -3595,10 +3595,13 @@ function updateLicenseBadge(plan, expiresAt) {
3595
3595
 
3596
3596
  badge.className = "license-badge";
3597
3597
 
3598
- if (plan === "pro") {
3598
+ if (plan === "pro" || plan === "pro_trial") {
3599
3599
  if (expiresAt && new Date(expiresAt) < new Date()) {
3600
3600
  badge.classList.add("expired");
3601
3601
  badge.textContent = "EXPIRED";
3602
+ } else if (plan === "pro_trial") {
3603
+ badge.classList.add("pro");
3604
+ badge.textContent = "TRIAL-PRO";
3602
3605
  } else {
3603
3606
  badge.classList.add("pro");
3604
3607
  badge.textContent = "PRO";
@@ -3866,11 +3869,11 @@ function setupLicenseModal() {
3866
3869
  body: JSON.stringify({ key }),
3867
3870
  });
3868
3871
  const data = await res.json();
3869
- if (data.success && data.plan === "pro") {
3872
+ if (data.success && (data.plan === "pro" || data.plan === "pro_trial")) {
3870
3873
  statusEl.className = "success";
3871
- statusEl.textContent = "PRO ACTIVATED";
3872
- updateLicenseBadge("pro", data.expiresAt);
3873
- updateLicenseButton("pro");
3874
+ statusEl.textContent = data.plan === "pro_trial" ? "TRIAL-PRO ACTIVATED" : "PRO ACTIVATED";
3875
+ updateLicenseBadge(data.plan, data.expiresAt);
3876
+ updateLicenseButton(data.plan);
3874
3877
  setTimeout(closeModal, 1200);
3875
3878
  } else {
3876
3879
  statusEl.className = "error";
@@ -3917,7 +3920,7 @@ function setupLicenseModal() {
3917
3920
  function updateLicenseButton(plan) {
3918
3921
  const btn = document.getElementById("btn-license");
3919
3922
  if (!btn) return;
3920
- btn.textContent = plan === "pro" ? "LICENSED" : "LICENSE";
3923
+ btn.textContent = (plan === "pro" || plan === "pro_trial") ? "LICENSED" : "LICENSE";
3921
3924
  }
3922
3925
 
3923
3926
  function setupProjectModal() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@syke1/mcp-server",
3
- "version": "1.4.3",
3
+ "version": "1.4.4",
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",