@vibekiln/cutline-mcp-cli 0.4.0 → 0.4.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/dist/auth/keychain.js
CHANGED
|
@@ -7093,7 +7093,7 @@ function deltaStr(current, previous) {
|
|
|
7093
7093
|
return " (no change)";
|
|
7094
7094
|
return diff > 0 ? ` (**+${diff}** since last scan)` : ` (**${diff}** since last scan)`;
|
|
7095
7095
|
}
|
|
7096
|
-
function formatAuditOutput(result, reportId, publicSiteUrl = "https://thecutline.ai", hiddenAuditDimensions = []) {
|
|
7096
|
+
function formatAuditOutput(result, reportId, publicSiteUrl = "https://thecutline.ai", hiddenAuditDimensions = [], fullReport = false) {
|
|
7097
7097
|
const m = result.metrics;
|
|
7098
7098
|
const p = result.previousMetrics;
|
|
7099
7099
|
const isRescan = !!p;
|
|
@@ -7181,24 +7181,32 @@ function formatAuditOutput(result, reportId, publicSiteUrl = "https://thecutline
|
|
|
7181
7181
|
const totalFindings = visibleFindings.length;
|
|
7182
7182
|
const criticalCount = visibleFindings.filter((g) => g.severity === "critical" || g.severity === "high").length;
|
|
7183
7183
|
if (totalFindings > 0) {
|
|
7184
|
-
|
|
7185
|
-
|
|
7186
|
-
|
|
7187
|
-
|
|
7188
|
-
lines.push(``, `## ${remaining.length} More Finding${remaining.length > 1 ? "s" : ""} Detected`);
|
|
7189
|
-
const teaserLimit = Math.min(remaining.length, 5);
|
|
7190
|
-
for (let i = 0; i < teaserLimit; i++) {
|
|
7191
|
-
lines.push(`- [${remaining[i].severity.toUpperCase()}] ${remaining[i].title}`);
|
|
7184
|
+
if (fullReport) {
|
|
7185
|
+
lines.push(``, `## Findings`, ``);
|
|
7186
|
+
for (const finding of visibleFindings) {
|
|
7187
|
+
lines.push(`**[${finding.severity.toUpperCase()}] ${finding.title}**`, `*Category: ${finding.category}*`, finding.description || "Address this finding to improve your readiness scores.", ``);
|
|
7192
7188
|
}
|
|
7193
|
-
|
|
7194
|
-
|
|
7189
|
+
lines.push(`> Re-run \`code_audit\` after fixes to measure score improvements.`);
|
|
7190
|
+
} else {
|
|
7191
|
+
const topFinding = visibleFindings[0];
|
|
7192
|
+
lines.push(``, `## #1 Finding \u2014 Fix This Now`, ``, `**[${topFinding.severity.toUpperCase()}] ${topFinding.title}**`, `*Category: ${topFinding.category}*`, ``, topFinding.description || "Address this finding to improve your readiness scores.", ``, `> Fix this issue, then re-run \`code_audit\` to see your scores improve.`);
|
|
7193
|
+
const remaining = visibleFindings.slice(1);
|
|
7194
|
+
if (remaining.length > 0) {
|
|
7195
|
+
lines.push(``, `## ${remaining.length} More Finding${remaining.length > 1 ? "s" : ""} Detected`);
|
|
7196
|
+
const teaserLimit = Math.min(remaining.length, 5);
|
|
7197
|
+
for (let i = 0; i < teaserLimit; i++) {
|
|
7198
|
+
lines.push(`- [${remaining[i].severity.toUpperCase()}] ${remaining[i].title}`);
|
|
7199
|
+
}
|
|
7200
|
+
if (remaining.length > teaserLimit) {
|
|
7201
|
+
lines.push(`- ... and **${remaining.length - teaserLimit} more**`);
|
|
7202
|
+
}
|
|
7195
7203
|
}
|
|
7196
7204
|
}
|
|
7197
7205
|
}
|
|
7198
7206
|
lines.push(``, `---`, ``);
|
|
7199
|
-
if (totalFindings > 1) {
|
|
7207
|
+
if (!fullReport && totalFindings > 1) {
|
|
7200
7208
|
lines.push(`### Unlock Full Analysis`, ``, `You fixed one \u2014 **${totalFindings - 1} findings** remain (${criticalCount} critical/high).`, `Upgrade to Cutline Pro for:`, `- Full details and remediation for every finding`, `- Prioritized RGR remediation plans your coding agent can execute`, `- Product-specific deep dive with feature-level constraint mapping`, `- Continuous score tracking with this audit as a baseline prior`, ``, `\u2192 Run \`cutline-mcp upgrade\` or visit **https://thecutline.ai/upgrade**`);
|
|
7201
|
-
} else if (totalFindings
|
|
7209
|
+
} else if (totalFindings >= 1) {
|
|
7202
7210
|
lines.push(`### Next Steps`, ``, `Fix the finding above, then re-scan to see your scores improve.`, `When ready, run a **deep dive** for product-specific analysis \u2014`, `these generic scores will serve as a prior for your product graph.`);
|
|
7203
7211
|
} else {
|
|
7204
7212
|
lines.push(`### Next Steps`, ``, `No critical findings detected. Run a **deep dive** for product-specific`, `analysis with feature coverage and the generic scores as a prior.`);
|
|
@@ -8423,15 +8431,17 @@ Why AI: ${idea.whyAI}`
|
|
|
8423
8431
|
return "engineering";
|
|
8424
8432
|
return "security";
|
|
8425
8433
|
};
|
|
8434
|
+
let hasPremiumSubscription = false;
|
|
8426
8435
|
{
|
|
8427
8436
|
const rateInfo = await getScanRateLimit();
|
|
8437
|
+
hasPremiumSubscription = rateInfo.subscription === "active" || rateInfo.subscription === "trialing";
|
|
8428
8438
|
const now = /* @__PURE__ */ new Date();
|
|
8429
8439
|
const resetAt = rateInfo.periodStart ? new Date(rateInfo.periodStart) : /* @__PURE__ */ new Date(0);
|
|
8430
8440
|
const monthStart = new Date(now.getFullYear(), now.getMonth(), 1);
|
|
8431
8441
|
if (resetAt < monthStart) {
|
|
8432
8442
|
await updateScanRateLimit({ free_scan_counter: { count: 1, reset_at: now.toISOString() } });
|
|
8433
8443
|
} else if (rateInfo.scanCount >= 3) {
|
|
8434
|
-
if (
|
|
8444
|
+
if (!hasPremiumSubscription) {
|
|
8435
8445
|
throw new McpError(ErrorCode.InvalidRequest, "Free scan limit reached (3/month). Run `cutline-mcp upgrade` in your terminal, or visit https://thecutline.ai/upgrade");
|
|
8436
8446
|
}
|
|
8437
8447
|
} else {
|
|
@@ -8500,7 +8510,7 @@ Why AI: ${idea.whyAI}`
|
|
|
8500
8510
|
console.error("[code_audit] Report persistence failed (non-fatal):", e);
|
|
8501
8511
|
}
|
|
8502
8512
|
return {
|
|
8503
|
-
content: [{ type: "text", text: formatAuditOutput(result, reportId, reportSiteUrl, hiddenAuditDimensions) }]
|
|
8513
|
+
content: [{ type: "text", text: formatAuditOutput(result, reportId, reportSiteUrl, hiddenAuditDimensions, hasPremiumSubscription) }]
|
|
8504
8514
|
};
|
|
8505
8515
|
}
|
|
8506
8516
|
const authCtx = await resolveAuthContext(args.auth_token);
|
|
@@ -12,6 +12,13 @@ export function saveConfig(config) {
|
|
|
12
12
|
ensureConfigDir();
|
|
13
13
|
const current = loadConfig();
|
|
14
14
|
const newConfig = { ...current, ...config };
|
|
15
|
+
// Treat explicit undefined values as key deletion so callers can clear
|
|
16
|
+
// persisted fields (for example during logout).
|
|
17
|
+
for (const [key, value] of Object.entries(config)) {
|
|
18
|
+
if (value === undefined) {
|
|
19
|
+
delete newConfig[key];
|
|
20
|
+
}
|
|
21
|
+
}
|
|
15
22
|
// Remove legacy fields that are no longer stored (e.g. firebaseApiKey)
|
|
16
23
|
// to prevent stale values from causing cross-project auth mismatches
|
|
17
24
|
delete newConfig.firebaseApiKey;
|
package/package.json
CHANGED