tandem-editor 0.16.0 → 0.17.0
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/.claude-plugin/plugin.json +3 -3
- package/CHANGELOG.md +24 -1
- package/dist/cli/index.js +310 -9
- package/dist/cli/index.js.map +1 -1
- package/dist/client/assets/{CoworkSettings-B4LapjhG.js → CoworkSettings-Brg8F0cb.js} +1 -1
- package/dist/client/assets/{dist-CJtsfiU2.js → dist-CHppK3gQ.js} +1 -1
- package/dist/client/assets/index-Boow3rxN.css +1 -0
- package/dist/client/assets/index-BymYYAwj.js +271 -0
- package/dist/client/assets/{prod-p35ShryZ.js → prod-Pu_njNLv.js} +1 -1
- package/dist/client/index.html +21 -5
- package/dist/server/index.js +308 -8
- package/dist/server/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/client/assets/index-BIEOrpU_.js +0 -270
- package/dist/client/assets/index-DdjGUhNd.css +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{U as e}from"./index-
|
|
1
|
+
import{U as e}from"./index-BymYYAwj.js";var t=typeof __SENTRY_DEBUG__>`u`||__SENTRY_DEBUG__,n=globalThis,r=`10.56.0`;function i(){return a(n),n}function a(e){let t=e.__SENTRY__=e.__SENTRY__||{};return t.version=t.version||`10.56.0`,t[r]=t[`10.56.0`]||{}}function o(e,t,i=n){let a=i.__SENTRY__=i.__SENTRY__||{},o=a[r]=a[`10.56.0`]||{};return o[e]||(o[e]=t())}var s=[`debug`,`info`,`warn`,`error`,`log`,`assert`,`trace`],c=`Sentry Logger `,l={};function u(e){if(!(`console`in n))return e();let t=n.console,r={},i=Object.keys(l);i.forEach(e=>{let n=l[e];r[e]=t[e],t[e]=n});try{return e()}finally{i.forEach(e=>{t[e]=r[e]})}}function d(){v().enabled=!0}function f(){v().enabled=!1}function p(){return v().enabled}function m(...e){_(`log`,...e)}function h(...e){_(`warn`,...e)}function g(...e){_(`error`,...e)}function _(e,...r){t&&p()&&u(()=>{n.console[e](`${c}[${e}]:`,...r)})}function v(){return t?o(`loggerSettings`,()=>({enabled:!1})):{enabled:!1}}var y={enable:d,disable:f,isEnabled:p,log:m,warn:h,error:g},b=50,x=/\(error: (.*)\)/,S=/captureMessage|captureException/;function C(...e){let t=e.sort((e,t)=>e[0]-t[0]).map(e=>e[1]);return(e,n=0,r=0)=>{let i=[],a=e.split(`
|
|
2
2
|
`);for(let e=n;e<a.length;e++){let n=a[e];n.length>1024&&(n=n.slice(0,1024));let o=x.test(n)?n.replace(x,`$1`):n;if(!o.includes(`Error: `)){for(let e of t){let t=e(o);if(t){i.push(t);break}}if(i.length>=b+r)break}}return T(i.slice(r))}}function w(e){return Array.isArray(e)?C(...e):e}function T(e){if(!e.length)return[];let t=Array.from(e);return/sentryWrapped/.test(ee(t).function||``)&&t.pop(),t.reverse(),S.test(ee(t).function||``)&&(t.pop(),S.test(ee(t).function||``)&&t.pop()),t.slice(0,b).map(e=>({...e,filename:e.filename||ee(t).filename,function:e.function||`?`}))}function ee(e){return e[e.length-1]||{}}var te=`<anonymous>`;function E(e){try{return!e||typeof e!=`function`?te:e.name||te}catch{return te}}function ne(e){let t=e.exception;if(t){let e=[];try{return t.values.forEach(t=>{t.stacktrace.frames&&e.push(...t.stacktrace.frames)}),e}catch{return}}}function re(e){let t=e?.startsWith(`file://`)?e.slice(7):e;return t?.match(/\/[A-Z]:/)&&(t=t.slice(1)),t}var ie={},ae={};function oe(e,t){return ie[e]=ie[e]||[],ie[e].push(t),()=>{let n=ie[e];if(n){let e=n.indexOf(t);e!==-1&&n.splice(e,1)}}}function D(e,n){if(!ae[e]){ae[e]=!0;try{n()}catch(n){t&&y.error(`Error while instrumenting ${e}`,n)}}}function O(e,n){let r=e&&ie[e];if(r)for(let i of r)try{i(n)}catch(n){t&&y.error(`Error while triggering instrumentation handler.
|
|
3
3
|
Type: ${e}
|
|
4
4
|
Name: ${E(i)}
|
package/dist/client/index.html
CHANGED
|
@@ -276,14 +276,30 @@
|
|
|
276
276
|
tab pills, +/add pill, mode segment, status pill, mini-toolbar,
|
|
277
277
|
wincontrols. Surfaces only need .tandem-floating-pill + a sensible
|
|
278
278
|
border-radius (pill or 14px). Surface-specific overrides (padding,
|
|
279
|
-
max-width, drag-region) layer on top.
|
|
279
|
+
max-width, drag-region) layer on top.
|
|
280
|
+
Deliberately NO backdrop-filter. --tandem-surface is opaque in
|
|
281
|
+
every theme, so a blur behind it never shows on the opaque consumers —
|
|
282
|
+
but this rule also reaches the ONE transparent consumer, the
|
|
283
|
+
selection-popup shell, where it painted a stray frosted rect in
|
|
284
|
+
PRODUCTION ONLY, and no scoped reset can be relied on to cancel it.
|
|
285
|
+
Why the asymmetry: THIS FILE'S inline \3c style> is emitted verbatim —
|
|
286
|
+
Vite never runs it through lightningcss — so a blur written here
|
|
287
|
+
reaches the browser exactly as typed. A component's `backdrop-filter:
|
|
288
|
+
none` reset does NOT: component CSS IS minified, and lightningcss
|
|
289
|
+
collapses a hand-written `backdrop-filter` + `-webkit-backdrop-filter`
|
|
290
|
+
pair (prefixed line last) into the `-webkit-` form alone, which
|
|
291
|
+
Chromium never implemented. So the recipe's blur survived while the
|
|
292
|
+
reset evaporated — the bug needed both halves. See #1188 and lesson 83.
|
|
293
|
+
Don't re-add a blur here: it buys nothing on an opaque surface, and the
|
|
294
|
+
override that would contain it cannot survive the other pipeline. If you
|
|
295
|
+
ever DO need a prefixed property in this file, hand-write the pair —
|
|
296
|
+
nothing autoprefixes index.html. That rule inverts in component CSS,
|
|
297
|
+
where hand-writing the pair is the bug. */
|
|
280
298
|
.tandem-floating-pill {
|
|
281
299
|
background: var(--tandem-surface);
|
|
282
300
|
border: 1px solid var(--tandem-border);
|
|
283
301
|
border-radius: var(--tandem-r-pill);
|
|
284
302
|
box-shadow: var(--c7-pill-shadow);
|
|
285
|
-
backdrop-filter: saturate(140%) blur(8px);
|
|
286
|
-
-webkit-backdrop-filter: saturate(140%) blur(8px);
|
|
287
303
|
}
|
|
288
304
|
[data-theme="dark"] .tandem-floating-pill {
|
|
289
305
|
--c7-pill-shadow:
|
|
@@ -679,8 +695,8 @@
|
|
|
679
695
|
line-height: var(--tandem-ui-leading);
|
|
680
696
|
}
|
|
681
697
|
</style>
|
|
682
|
-
<script type="module" crossorigin src="/assets/index-
|
|
683
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
698
|
+
<script type="module" crossorigin src="/assets/index-BymYYAwj.js"></script>
|
|
699
|
+
<link rel="stylesheet" crossorigin href="/assets/index-Boow3rxN.css">
|
|
684
700
|
</head>
|
|
685
701
|
<body>
|
|
686
702
|
<div id="root"></div>
|
package/dist/server/index.js
CHANGED
|
@@ -93543,8 +93543,8 @@ function resolveChannelDist(env3 = process.env, exists = existsSync) {
|
|
|
93543
93543
|
return resolve3(PACKAGE_ROOT, "dist/channel/index.js");
|
|
93544
93544
|
}
|
|
93545
93545
|
function resolveCliVersion() {
|
|
93546
|
-
if (true) return "0.
|
|
93547
|
-
if (true) return "0.
|
|
93546
|
+
if (true) return "0.17.0";
|
|
93547
|
+
if (true) return "0.17.0";
|
|
93548
93548
|
for (const rel of ["../../package.json", "../../../package.json"]) {
|
|
93549
93549
|
try {
|
|
93550
93550
|
const pkg = JSON.parse(readFileSync2(resolve3(__dirname2, rel), "utf8"));
|
|
@@ -129433,6 +129433,10 @@ import { request } from "http";
|
|
|
129433
129433
|
import { createConnection } from "net";
|
|
129434
129434
|
import { homedir as homedir3, platform } from "os";
|
|
129435
129435
|
import { join as join5 } from "path";
|
|
129436
|
+
function errorClass(err) {
|
|
129437
|
+
if (err instanceof Error) return err.name;
|
|
129438
|
+
return typeof err;
|
|
129439
|
+
}
|
|
129436
129440
|
function checkNodeVersion(r) {
|
|
129437
129441
|
const version3 = process.version;
|
|
129438
129442
|
const major2 = Number.parseInt(version3.slice(1), 10);
|
|
@@ -129452,6 +129456,201 @@ function checkNodeModules(r) {
|
|
|
129452
129456
|
r.fail("node_modules/ not found", "npm install");
|
|
129453
129457
|
}
|
|
129454
129458
|
}
|
|
129459
|
+
function recordEvaluation(r, result2) {
|
|
129460
|
+
if (!result2) return;
|
|
129461
|
+
if (result2.status === "warn") {
|
|
129462
|
+
r.warn(result2.message, result2.fix, result2.data);
|
|
129463
|
+
return;
|
|
129464
|
+
}
|
|
129465
|
+
if (result2.status === "skip") {
|
|
129466
|
+
r.pass(`skipped \u2014 ${result2.message}`, result2.fix, { ...result2.data, skipped: true });
|
|
129467
|
+
return;
|
|
129468
|
+
}
|
|
129469
|
+
r.pass(result2.message, result2.fix, result2.data);
|
|
129470
|
+
}
|
|
129471
|
+
function probeTandemEditorRepo(dir) {
|
|
129472
|
+
const read = readJson2(join5(dir, "package.json"));
|
|
129473
|
+
if (read.kind === "absent") return "no";
|
|
129474
|
+
if (read.kind === "unreadable") return "unreadable";
|
|
129475
|
+
const parsed = read.value;
|
|
129476
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
129477
|
+
return "unreadable";
|
|
129478
|
+
}
|
|
129479
|
+
return parsed.name === "tandem-editor" ? "yes" : "no";
|
|
129480
|
+
}
|
|
129481
|
+
function readJson2(path33) {
|
|
129482
|
+
let raw;
|
|
129483
|
+
try {
|
|
129484
|
+
raw = readFileSync3(path33, "utf-8");
|
|
129485
|
+
} catch (err) {
|
|
129486
|
+
const code3 = err.code;
|
|
129487
|
+
if (code3 === "ENOENT") return { kind: "absent" };
|
|
129488
|
+
return { kind: "unreadable", reason: code3 ?? errorClass(err) };
|
|
129489
|
+
}
|
|
129490
|
+
try {
|
|
129491
|
+
return { kind: "ok", value: JSON.parse(raw) };
|
|
129492
|
+
} catch {
|
|
129493
|
+
return { kind: "unreadable", reason: "not valid JSON" };
|
|
129494
|
+
}
|
|
129495
|
+
}
|
|
129496
|
+
function parseLockfileEntry(value) {
|
|
129497
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return null;
|
|
129498
|
+
const entry = value;
|
|
129499
|
+
if (entry.version !== void 0 && typeof entry.version !== "string") return null;
|
|
129500
|
+
if (entry.optional !== void 0 && typeof entry.optional !== "boolean") return null;
|
|
129501
|
+
return {
|
|
129502
|
+
version: entry.version,
|
|
129503
|
+
optional: entry.optional
|
|
129504
|
+
};
|
|
129505
|
+
}
|
|
129506
|
+
function parseLockfileJson(value) {
|
|
129507
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return null;
|
|
129508
|
+
const obj2 = value;
|
|
129509
|
+
if (obj2.version !== void 0 && typeof obj2.version !== "string") return null;
|
|
129510
|
+
const version3 = obj2.version;
|
|
129511
|
+
if (obj2.packages === void 0) return { version: version3 };
|
|
129512
|
+
if (typeof obj2.packages !== "object" || obj2.packages === null || Array.isArray(obj2.packages)) {
|
|
129513
|
+
return null;
|
|
129514
|
+
}
|
|
129515
|
+
const packages = {};
|
|
129516
|
+
for (const [path33, raw] of Object.entries(obj2.packages)) {
|
|
129517
|
+
const entry = parseLockfileEntry(raw);
|
|
129518
|
+
if (!entry) return null;
|
|
129519
|
+
packages[path33] = entry;
|
|
129520
|
+
}
|
|
129521
|
+
return { version: version3, packages };
|
|
129522
|
+
}
|
|
129523
|
+
function evaluateNpmStaleness(pkgInput, lockInput, hiddenLockInput) {
|
|
129524
|
+
if (!pkgInput || !lockInput || !hiddenLockInput) return null;
|
|
129525
|
+
const lock = parseLockfileJson(lockInput);
|
|
129526
|
+
if (!lock) {
|
|
129527
|
+
return {
|
|
129528
|
+
status: "skip",
|
|
129529
|
+
message: "cannot compare (package-lock.json has an unexpected structure)",
|
|
129530
|
+
fix: "Restore it from git: git checkout package-lock.json",
|
|
129531
|
+
data: { reason: "malformed-lock" }
|
|
129532
|
+
};
|
|
129533
|
+
}
|
|
129534
|
+
const hiddenLock = parseLockfileJson(hiddenLockInput);
|
|
129535
|
+
if (!hiddenLock) {
|
|
129536
|
+
return {
|
|
129537
|
+
status: "skip",
|
|
129538
|
+
message: "cannot compare (node_modules/.package-lock.json has an unexpected structure)",
|
|
129539
|
+
fix: "npm install",
|
|
129540
|
+
data: { reason: "malformed-hidden-lock" }
|
|
129541
|
+
};
|
|
129542
|
+
}
|
|
129543
|
+
const pkg = typeof pkgInput === "object" && !Array.isArray(pkgInput) ? pkgInput : {};
|
|
129544
|
+
const pkgVersion = typeof pkg.version === "string" ? pkg.version : void 0;
|
|
129545
|
+
if (pkgVersion && lock.version && pkgVersion !== lock.version) {
|
|
129546
|
+
return {
|
|
129547
|
+
status: "warn",
|
|
129548
|
+
message: `package-lock.json (v${lock.version}) is out of date with package.json (v${pkgVersion})`,
|
|
129549
|
+
fix: "npm install",
|
|
129550
|
+
data: { packageVersion: pkgVersion, lockVersion: lock.version }
|
|
129551
|
+
};
|
|
129552
|
+
}
|
|
129553
|
+
if (lock.version && hiddenLock.version && lock.version !== hiddenLock.version) {
|
|
129554
|
+
return {
|
|
129555
|
+
status: "warn",
|
|
129556
|
+
message: `node_modules was installed from a different lockfile (v${hiddenLock.version} installed, v${lock.version} expected)`,
|
|
129557
|
+
fix: "npm install",
|
|
129558
|
+
data: { lockVersion: lock.version, installedVersion: hiddenLock.version }
|
|
129559
|
+
};
|
|
129560
|
+
}
|
|
129561
|
+
const wanted = lock.packages ?? {};
|
|
129562
|
+
const installed = hiddenLock.packages ?? {};
|
|
129563
|
+
const wantedCount = Object.keys(wanted).filter((path33) => path33 !== "").length;
|
|
129564
|
+
if (wantedCount === 0) {
|
|
129565
|
+
return {
|
|
129566
|
+
status: "skip",
|
|
129567
|
+
message: "cannot compare (package-lock.json lists no packages \u2014 a lockfileVersion 1 file, or one written by something other than npm)",
|
|
129568
|
+
fix: "npm install",
|
|
129569
|
+
// No inferred `lockfileVersion` here: we did not read that field, and
|
|
129570
|
+
// guessing it from the presence of `packages` would put a fabricated
|
|
129571
|
+
// value under a real npm field name.
|
|
129572
|
+
data: { reason: "no-comparable-packages" }
|
|
129573
|
+
};
|
|
129574
|
+
}
|
|
129575
|
+
const drifted = [];
|
|
129576
|
+
for (const [path33, entry] of Object.entries(wanted)) {
|
|
129577
|
+
if (path33 === "") continue;
|
|
129578
|
+
const got = installed[path33];
|
|
129579
|
+
if (!got) {
|
|
129580
|
+
if (!entry.optional) drifted.push(path33);
|
|
129581
|
+
} else if (entry.version !== got.version) {
|
|
129582
|
+
drifted.push(path33);
|
|
129583
|
+
}
|
|
129584
|
+
}
|
|
129585
|
+
for (const path33 of Object.keys(installed)) {
|
|
129586
|
+
if (path33 !== "" && !(path33 in wanted)) drifted.push(path33);
|
|
129587
|
+
}
|
|
129588
|
+
if (drifted.length > 0) {
|
|
129589
|
+
return {
|
|
129590
|
+
status: "warn",
|
|
129591
|
+
message: `node_modules is stale \u2014 ${drifted.length} package(s) differ from package-lock.json (e.g. after a pull or branch switch)`,
|
|
129592
|
+
fix: "npm install",
|
|
129593
|
+
data: { driftCount: drifted.length, sample: drifted.slice(0, 5) }
|
|
129594
|
+
};
|
|
129595
|
+
}
|
|
129596
|
+
const missingVersions = [];
|
|
129597
|
+
if (!pkgVersion) missingVersions.push("package.json");
|
|
129598
|
+
if (!lock.version) missingVersions.push("package-lock.json");
|
|
129599
|
+
if (!hiddenLock.version) missingVersions.push("node_modules/.package-lock.json");
|
|
129600
|
+
if (missingVersions.length > 0) {
|
|
129601
|
+
return {
|
|
129602
|
+
status: "skip",
|
|
129603
|
+
message: `node_modules matches package-lock.json, but the version check could not run \u2014 no "version" field in ${missingVersions.join(", ")}`,
|
|
129604
|
+
data: { reason: "no-comparable-version", missingVersions }
|
|
129605
|
+
};
|
|
129606
|
+
}
|
|
129607
|
+
return {
|
|
129608
|
+
status: "pass",
|
|
129609
|
+
message: "node_modules matches package-lock.json",
|
|
129610
|
+
data: { packageCount: Object.keys(installed).length }
|
|
129611
|
+
};
|
|
129612
|
+
}
|
|
129613
|
+
function readLockfileOrReport(r, path33, label) {
|
|
129614
|
+
const read = readJson2(path33);
|
|
129615
|
+
if (read.kind === "absent") {
|
|
129616
|
+
r.pass(`skipped \u2014 cannot compare (${label} not found)`, void 0, {
|
|
129617
|
+
skipped: true,
|
|
129618
|
+
reason: "absent",
|
|
129619
|
+
path: label
|
|
129620
|
+
});
|
|
129621
|
+
return { ok: false };
|
|
129622
|
+
}
|
|
129623
|
+
if (read.kind === "ok") {
|
|
129624
|
+
if (typeof read.value === "object" && read.value !== null && !Array.isArray(read.value)) {
|
|
129625
|
+
return { ok: true, value: read.value };
|
|
129626
|
+
}
|
|
129627
|
+
r.warn(
|
|
129628
|
+
`${label} is not a JSON object \u2014 npm install staleness cannot be checked`,
|
|
129629
|
+
"Check for a truncated or hand-edited file, then: npm install",
|
|
129630
|
+
{ reason: "not-an-object", path: label }
|
|
129631
|
+
);
|
|
129632
|
+
return { ok: false };
|
|
129633
|
+
}
|
|
129634
|
+
r.warn(
|
|
129635
|
+
`${label} could not be read (${read.reason}) \u2014 npm install staleness cannot be checked`,
|
|
129636
|
+
"Check for merge-conflict markers or a truncated file, then: npm install",
|
|
129637
|
+
{ reason: read.reason, path: label }
|
|
129638
|
+
);
|
|
129639
|
+
return { ok: false };
|
|
129640
|
+
}
|
|
129641
|
+
function checkNpmStaleness(r, repoDir) {
|
|
129642
|
+
const pkgRead = readJson2(join5(repoDir, "package.json"));
|
|
129643
|
+
const pkg = pkgRead.kind === "ok" ? pkgRead.value : null;
|
|
129644
|
+
const lock = readLockfileOrReport(r, join5(repoDir, "package-lock.json"), "package-lock.json");
|
|
129645
|
+
if (!lock.ok) return;
|
|
129646
|
+
const hiddenLock = readLockfileOrReport(
|
|
129647
|
+
r,
|
|
129648
|
+
join5(repoDir, "node_modules", ".package-lock.json"),
|
|
129649
|
+
"node_modules/.package-lock.json"
|
|
129650
|
+
);
|
|
129651
|
+
if (!hiddenLock.ok) return;
|
|
129652
|
+
recordEvaluation(r, evaluateNpmStaleness(pkg, lock.value, hiddenLock.value));
|
|
129653
|
+
}
|
|
129455
129654
|
function checkMcpJson(r) {
|
|
129456
129655
|
const mcpPath = join5(process.cwd(), ".mcp.json");
|
|
129457
129656
|
if (!existsSync2(mcpPath)) {
|
|
@@ -129577,14 +129776,64 @@ async function checkPorts(r, wsPort2, mcpPort2) {
|
|
|
129577
129776
|
}
|
|
129578
129777
|
return { ws, mcp };
|
|
129579
129778
|
}
|
|
129779
|
+
function evaluateOrphanedVite(input) {
|
|
129780
|
+
const { viteUp, viteConfirmed, wsUp, mcpUp, wsPort: wsPort2, mcpPort: mcpPort2, vitePort } = input;
|
|
129781
|
+
if (!viteUp) return null;
|
|
129782
|
+
if (!viteConfirmed) {
|
|
129783
|
+
return {
|
|
129784
|
+
status: "skip",
|
|
129785
|
+
message: `cannot identify the process on :${vitePort} \u2014 it is listening but did not answer /@vite/client, so it is probably not a Vite dev server`,
|
|
129786
|
+
data: { vite: false, ws: wsUp, mcp: mcpUp, reason: "unconfirmed-vite" }
|
|
129787
|
+
};
|
|
129788
|
+
}
|
|
129789
|
+
if (!wsUp && !mcpUp) {
|
|
129790
|
+
return {
|
|
129791
|
+
status: "warn",
|
|
129792
|
+
message: `Vite dev server on :${vitePort} is running but the backend (:${wsPort2} + :${mcpPort2}) is down \u2014 likely orphaned by a crashed dev session`,
|
|
129793
|
+
fix: `If you meant to run the client alone (npm run dev:client), this is expected. Otherwise kill the process on :${vitePort} and restart: npm run dev:standalone`,
|
|
129794
|
+
data: { vite: true, ws: wsUp, mcp: mcpUp }
|
|
129795
|
+
};
|
|
129796
|
+
}
|
|
129797
|
+
if (wsUp !== mcpUp) {
|
|
129798
|
+
return {
|
|
129799
|
+
status: "skip",
|
|
129800
|
+
message: `cannot tell whether the Vite dev server on :${vitePort} is orphaned \u2014 the backend is only partially up (:${wsPort2} ${wsUp ? "up" : "down"}, :${mcpPort2} ${mcpUp ? "up" : "down"}); see the ports check`,
|
|
129801
|
+
data: { vite: true, ws: wsUp, mcp: mcpUp, reason: "partial-backend" }
|
|
129802
|
+
};
|
|
129803
|
+
}
|
|
129804
|
+
return {
|
|
129805
|
+
status: "pass",
|
|
129806
|
+
message: `Vite dev server (:${vitePort}) running alongside the backend`,
|
|
129807
|
+
data: { vite: true, ws: wsUp, mcp: mcpUp }
|
|
129808
|
+
};
|
|
129809
|
+
}
|
|
129810
|
+
async function checkOrphanedVite(r, wsUp, mcpUp, wsPort2, mcpPort2, vitePort) {
|
|
129811
|
+
const viteUp = await probePort(vitePort);
|
|
129812
|
+
const viteConfirmed = viteUp ? await isViteDevServer(vitePort) : false;
|
|
129813
|
+
recordEvaluation(
|
|
129814
|
+
r,
|
|
129815
|
+
evaluateOrphanedVite({ viteUp, viteConfirmed, wsUp, mcpUp, wsPort: wsPort2, mcpPort: mcpPort2, vitePort })
|
|
129816
|
+
);
|
|
129817
|
+
}
|
|
129580
129818
|
function httpGet(url, timeoutMs = 3e3) {
|
|
129581
129819
|
return new Promise((resolve5) => {
|
|
129582
129820
|
const req = request(url, { timeout: timeoutMs }, (res) => {
|
|
129583
129821
|
let body = "";
|
|
129822
|
+
let bytes = 0;
|
|
129823
|
+
let truncated = false;
|
|
129584
129824
|
res.on("data", (chunk2) => {
|
|
129825
|
+
if (truncated) return;
|
|
129826
|
+
bytes += Buffer.byteLength(chunk2);
|
|
129827
|
+
if (bytes > HTTP_MAX_BYTES) {
|
|
129828
|
+
truncated = true;
|
|
129829
|
+
res.destroy();
|
|
129830
|
+
resolve5({ status: res.statusCode, data: null });
|
|
129831
|
+
return;
|
|
129832
|
+
}
|
|
129585
129833
|
body += chunk2;
|
|
129586
129834
|
});
|
|
129587
129835
|
res.on("end", () => {
|
|
129836
|
+
if (truncated) return;
|
|
129588
129837
|
try {
|
|
129589
129838
|
resolve5({ status: res.statusCode, data: JSON.parse(body) });
|
|
129590
129839
|
} catch {
|
|
@@ -129600,6 +129849,10 @@ function httpGet(url, timeoutMs = 3e3) {
|
|
|
129600
129849
|
req.end();
|
|
129601
129850
|
});
|
|
129602
129851
|
}
|
|
129852
|
+
async function isViteDevServer(port) {
|
|
129853
|
+
const result2 = await httpGet(`http://127.0.0.1:${port}/@vite/client`, 2e3);
|
|
129854
|
+
return result2?.status === 200;
|
|
129855
|
+
}
|
|
129603
129856
|
async function checkHealth(r, mcpPort2) {
|
|
129604
129857
|
const result2 = await httpGet(`http://127.0.0.1:${mcpPort2}/health`);
|
|
129605
129858
|
if (!result2) {
|
|
@@ -129839,7 +130092,7 @@ function evaluateStaleGlobal(bundled, globalVersion) {
|
|
|
129839
130092
|
};
|
|
129840
130093
|
}
|
|
129841
130094
|
async function checkStaleGlobal(r) {
|
|
129842
|
-
const bundled = true ? "0.
|
|
130095
|
+
const bundled = true ? "0.17.0" : null;
|
|
129843
130096
|
if (!bundled) return;
|
|
129844
130097
|
let globalVersion;
|
|
129845
130098
|
try {
|
|
@@ -129858,16 +130111,37 @@ async function checkStaleGlobal(r) {
|
|
|
129858
130111
|
async function runDoctor(opts = {}) {
|
|
129859
130112
|
const wsPort2 = opts.wsPort ?? DEFAULT_WS_PORT;
|
|
129860
130113
|
const mcpPort2 = opts.mcpPort ?? DEFAULT_MCP_PORT;
|
|
130114
|
+
const vitePort = opts.vitePort ?? VITE_DEV_PORT;
|
|
129861
130115
|
const r = new Recorder();
|
|
130116
|
+
const cwd = process.cwd();
|
|
130117
|
+
const repo = probeTandemEditorRepo(cwd);
|
|
130118
|
+
const devRepo = repo === "yes";
|
|
129862
130119
|
await r.check("node-version", () => checkNodeVersion(r));
|
|
129863
130120
|
await r.check("node-modules", () => checkNodeModules(r));
|
|
130121
|
+
if (repo === "unreadable") {
|
|
130122
|
+
await r.check(
|
|
130123
|
+
"dev-repo",
|
|
130124
|
+
() => r.warn(
|
|
130125
|
+
"package.json in the current directory could not be read \u2014 if this is the tandem-editor checkout, the npm-staleness and orphaned-Vite checks are being skipped",
|
|
130126
|
+
"Check for merge-conflict markers or a truncated file: git checkout package.json"
|
|
130127
|
+
)
|
|
130128
|
+
);
|
|
130129
|
+
}
|
|
130130
|
+
if (devRepo) {
|
|
130131
|
+
await r.check("npm-staleness", () => checkNpmStaleness(r, cwd));
|
|
130132
|
+
}
|
|
129864
130133
|
await r.check("mcp-json", () => checkMcpJson(r));
|
|
129865
130134
|
await r.check("user-mcp-config", () => checkUserMcpConfig(r));
|
|
129866
130135
|
await r.check("annotation-store", () => checkAnnotationStore(r));
|
|
129867
130136
|
await r.check("stale-global", () => checkStaleGlobal(r));
|
|
129868
|
-
const
|
|
130137
|
+
const ports = await r.check("ports", () => checkPorts(r, wsPort2, mcpPort2));
|
|
130138
|
+
const ws = ports?.ws ?? false;
|
|
130139
|
+
const mcp = ports?.mcp ?? false;
|
|
130140
|
+
if (devRepo) {
|
|
130141
|
+
await r.check("orphaned-vite", () => checkOrphanedVite(r, ws, mcp, wsPort2, mcpPort2, vitePort));
|
|
130142
|
+
}
|
|
129869
130143
|
if (mcp) {
|
|
129870
|
-
const healthy = await r.check("health", () => checkHealth(r, mcpPort2));
|
|
130144
|
+
const healthy = await r.check("health", () => checkHealth(r, mcpPort2)) ?? false;
|
|
129871
130145
|
if (healthy) {
|
|
129872
130146
|
await r.check("sse", () => checkSseEndpoint(r, mcpPort2));
|
|
129873
130147
|
}
|
|
@@ -129882,7 +130156,7 @@ async function runDoctor(opts = {}) {
|
|
|
129882
130156
|
results: r.results
|
|
129883
130157
|
};
|
|
129884
130158
|
}
|
|
129885
|
-
var Recorder;
|
|
130159
|
+
var Recorder, VITE_DEV_PORT, HTTP_MAX_BYTES;
|
|
129886
130160
|
var init_doctor = __esm({
|
|
129887
130161
|
"src/cli/doctor.ts"() {
|
|
129888
130162
|
"use strict";
|
|
@@ -129893,11 +130167,29 @@ var init_doctor = __esm({
|
|
|
129893
130167
|
warnings = 0;
|
|
129894
130168
|
results = [];
|
|
129895
130169
|
currentCheck = "";
|
|
130170
|
+
/**
|
|
130171
|
+
* Run one check under `name`. A throwing check is contained here and
|
|
130172
|
+
* recorded as a `fail` rather than taking the whole report down.
|
|
130173
|
+
*
|
|
130174
|
+
* Returns `T | undefined` — NOT `T`. The `undefined` is load-bearing and
|
|
130175
|
+
* must not be cast away: a crashed check produced no value, and the two
|
|
130176
|
+
* callers that consume one (`ports` destructures `{ws, mcp}`; `health`
|
|
130177
|
+
* gates the `sse` check) have to say what they want instead. Returning
|
|
130178
|
+
* `undefined as T` would satisfy the compiler and then throw a TypeError
|
|
130179
|
+
* on the destructure — converting a clear crash into a confusing one on
|
|
130180
|
+
* the exact path this containment exists to protect.
|
|
130181
|
+
*/
|
|
129896
130182
|
async check(name2, fn) {
|
|
129897
130183
|
const prev = this.currentCheck;
|
|
129898
130184
|
this.currentCheck = name2;
|
|
129899
130185
|
try {
|
|
129900
130186
|
return await fn();
|
|
130187
|
+
} catch (err) {
|
|
130188
|
+
this.fail(
|
|
130189
|
+
`${name2} check crashed (${errorClass(err)}) \u2014 the rest of the report is still valid`,
|
|
130190
|
+
"Please report this at https://github.com/bloknayrb/tandem/issues"
|
|
130191
|
+
);
|
|
130192
|
+
return void 0;
|
|
129901
130193
|
} finally {
|
|
129902
130194
|
this.currentCheck = prev;
|
|
129903
130195
|
}
|
|
@@ -129920,6 +130212,8 @@ var init_doctor = __esm({
|
|
|
129920
130212
|
this.record("fail", msg, fix, fields);
|
|
129921
130213
|
}
|
|
129922
130214
|
};
|
|
130215
|
+
VITE_DEV_PORT = 5173;
|
|
130216
|
+
HTTP_MAX_BYTES = 256 * 1024;
|
|
129923
130217
|
}
|
|
129924
130218
|
});
|
|
129925
130219
|
|
|
@@ -129974,7 +130268,13 @@ var init_diagnostics = __esm({
|
|
|
129974
130268
|
"use strict";
|
|
129975
130269
|
init_doctor();
|
|
129976
130270
|
init_middleware();
|
|
129977
|
-
DEV_REPO_CHECKS = /* @__PURE__ */ new Set([
|
|
130271
|
+
DEV_REPO_CHECKS = /* @__PURE__ */ new Set([
|
|
130272
|
+
"node-modules",
|
|
130273
|
+
"mcp-json",
|
|
130274
|
+
"npm-staleness",
|
|
130275
|
+
"orphaned-vite",
|
|
130276
|
+
"dev-repo"
|
|
130277
|
+
]);
|
|
129978
130278
|
}
|
|
129979
130279
|
});
|
|
129980
130280
|
|
|
@@ -188114,7 +188414,7 @@ init_document2();
|
|
|
188114
188414
|
init_document_service();
|
|
188115
188415
|
init_docx_apply2();
|
|
188116
188416
|
var esmRequire2 = createRequire2(import.meta.url);
|
|
188117
|
-
var APP_VERSION = true ? "0.
|
|
188417
|
+
var APP_VERSION = true ? "0.17.0" : _readVersionFromDisk();
|
|
188118
188418
|
var MCP_SDK_VERSION = true ? "1.27.1" : "0.0.0-unknown";
|
|
188119
188419
|
var __dirname3 = dirname3(fileURLToPath4(import.meta.url));
|
|
188120
188420
|
var CLIENT_DIST = join7(__dirname3, "../client");
|