drafted 1.11.37 → 1.11.38
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/mcp/server.mjs +80 -17
- package/package.json +1 -1
package/mcp/server.mjs
CHANGED
|
@@ -515,26 +515,89 @@ function mcpMode() {
|
|
|
515
515
|
return process.argv.includes('--http') ? 'http' : 'stdio';
|
|
516
516
|
}
|
|
517
517
|
|
|
518
|
+
// ponytail: reports that fail to send (e.g. server unreachable) queue here on disk
|
|
519
|
+
// instead of dropping silently, and get retried on the next tool call.
|
|
520
|
+
const PENDING_REPORTS_PATH = () => join(homedir(), '.drafted', 'pending-reports.jsonl');
|
|
521
|
+
const MAX_PENDING_REPORTS = 50;
|
|
522
|
+
|
|
523
|
+
function readPendingReports() {
|
|
524
|
+
try {
|
|
525
|
+
return readFileSync(PENDING_REPORTS_PATH(), 'utf8')
|
|
526
|
+
.split('\n')
|
|
527
|
+
.filter(Boolean)
|
|
528
|
+
.map((line) => { try { return JSON.parse(line); } catch { return null; } })
|
|
529
|
+
.filter(Boolean);
|
|
530
|
+
} catch {
|
|
531
|
+
return [];
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
function writePendingReports(reports) {
|
|
536
|
+
const reportsPath = PENDING_REPORTS_PATH();
|
|
537
|
+
if (!reports.length) {
|
|
538
|
+
try { unlinkSync(reportsPath); } catch { /* nothing to remove */ }
|
|
539
|
+
return;
|
|
540
|
+
}
|
|
541
|
+
try {
|
|
542
|
+
mkdirSync(dirname(reportsPath), { recursive: true });
|
|
543
|
+
writeFileSync(reportsPath, reports.slice(-MAX_PENDING_REPORTS).map((r) => JSON.stringify(r)).join('\n') + '\n', { mode: 0o600 });
|
|
544
|
+
} catch { /* best effort */ }
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
async function flushPendingReports(serverUrl) {
|
|
548
|
+
const pending = readPendingReports();
|
|
549
|
+
if (!pending.length) return;
|
|
550
|
+
const stillPending = [];
|
|
551
|
+
for (const body of pending) {
|
|
552
|
+
try {
|
|
553
|
+
await fetch(`${serverUrl}/api/installations/report`, {
|
|
554
|
+
method: 'POST',
|
|
555
|
+
headers: { 'Content-Type': 'application/json', 'User-Agent': `Drafted MCP/${PACKAGE_VERSION}` },
|
|
556
|
+
body: JSON.stringify(body),
|
|
557
|
+
});
|
|
558
|
+
} catch {
|
|
559
|
+
stillPending.push(body);
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
writePendingReports(stillPending);
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
// Serializes all report sends/flushes so rapid back-to-back tool calls (the common
|
|
566
|
+
// case during an outage, when a client retries repeatedly) don't race on a
|
|
567
|
+
// read-modify-write of the same pending-reports file and drop queued events.
|
|
568
|
+
let installReportChain = Promise.resolve();
|
|
569
|
+
|
|
570
|
+
async function sendInstallationReport(serverUrl, body) {
|
|
571
|
+
await flushPendingReports(serverUrl);
|
|
572
|
+
try {
|
|
573
|
+
await fetch(`${serverUrl}/api/installations/report`, {
|
|
574
|
+
method: 'POST',
|
|
575
|
+
headers: { 'Content-Type': 'application/json', 'User-Agent': `Drafted MCP/${PACKAGE_VERSION}` },
|
|
576
|
+
body: JSON.stringify(body),
|
|
577
|
+
});
|
|
578
|
+
} catch {
|
|
579
|
+
writePendingReports([...readPendingReports(), body]);
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
|
|
518
583
|
function reportInstallationEvent(event, extra = {}) {
|
|
519
584
|
const info = getInstallInfo();
|
|
520
585
|
if (!info) return;
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
}),
|
|
537
|
-
}).catch(() => {});
|
|
586
|
+
const serverUrl = getServerUrl();
|
|
587
|
+
const body = {
|
|
588
|
+
installId: info.installId,
|
|
589
|
+
event,
|
|
590
|
+
schemaVersion: 1,
|
|
591
|
+
cliVersion: PACKAGE_VERSION,
|
|
592
|
+
osFamily: osFamily(),
|
|
593
|
+
osVersion: osRelease().slice(0, 60),
|
|
594
|
+
arch: normalizedArch(),
|
|
595
|
+
nodeVersion: process.version,
|
|
596
|
+
mcpMode: mcpMode(),
|
|
597
|
+
source: 'mcp',
|
|
598
|
+
...extra,
|
|
599
|
+
};
|
|
600
|
+
installReportChain = installReportChain.then(() => sendInstallationReport(serverUrl, body)).catch(() => {});
|
|
538
601
|
}
|
|
539
602
|
|
|
540
603
|
function classifyMcpError(error) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "drafted",
|
|
3
|
-
"version": "1.11.
|
|
3
|
+
"version": "1.11.38",
|
|
4
4
|
"description": "Drafted — visual thinking surface for humans and AI agents. Renders HTML, markdown, images, and code as frames on a zoomable canvas, with MCP tools for AI agents and real-time sync for humans.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"files": [
|