tandem-editor 0.5.0 → 0.6.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/marketplace.json +19 -0
- package/.claude-plugin/plugin.json +27 -0
- package/CHANGELOG.md +55 -0
- package/README.md +27 -0
- package/dist/channel/index.js +156 -143
- package/dist/channel/index.js.map +1 -1
- package/dist/cli/index.js +718 -133
- package/dist/cli/index.js.map +1 -1
- package/dist/client/assets/index-mo5ZOPfU.js +349 -0
- package/dist/client/index.html +63 -2
- package/dist/monitor/index.js +4570 -0
- package/dist/monitor/index.js.map +1 -0
- package/dist/server/index.js +152 -221
- package/dist/server/index.js.map +1 -1
- package/package.json +5 -3
- package/skills/tandem/SKILL.md +93 -0
- package/dist/client/assets/index-BS8jwldm.js +0 -345
package/dist/server/index.js
CHANGED
|
@@ -8428,13 +8428,13 @@ var require_thenables = __commonJS({
|
|
|
8428
8428
|
promise._captureStackTrace();
|
|
8429
8429
|
if (context) context._popContext();
|
|
8430
8430
|
var synchronous = true;
|
|
8431
|
-
var result2 = util2.tryCatch(then).call(x,
|
|
8431
|
+
var result2 = util2.tryCatch(then).call(x, resolve3, reject2);
|
|
8432
8432
|
synchronous = false;
|
|
8433
8433
|
if (promise && result2 === errorObj2) {
|
|
8434
8434
|
promise._rejectCallback(result2.e, true, true);
|
|
8435
8435
|
promise = null;
|
|
8436
8436
|
}
|
|
8437
|
-
function
|
|
8437
|
+
function resolve3(value) {
|
|
8438
8438
|
if (!promise) return;
|
|
8439
8439
|
promise._resolveCallback(value);
|
|
8440
8440
|
promise = null;
|
|
@@ -8969,9 +8969,9 @@ var require_debuggability = __commonJS({
|
|
|
8969
8969
|
return false;
|
|
8970
8970
|
}
|
|
8971
8971
|
Promise2.prototype._fireEvent = defaultFireEvent;
|
|
8972
|
-
Promise2.prototype._execute = function(executor,
|
|
8972
|
+
Promise2.prototype._execute = function(executor, resolve3, reject2) {
|
|
8973
8973
|
try {
|
|
8974
|
-
executor(
|
|
8974
|
+
executor(resolve3, reject2);
|
|
8975
8975
|
} catch (e) {
|
|
8976
8976
|
return e;
|
|
8977
8977
|
}
|
|
@@ -8994,10 +8994,10 @@ var require_debuggability = __commonJS({
|
|
|
8994
8994
|
;
|
|
8995
8995
|
;
|
|
8996
8996
|
};
|
|
8997
|
-
function cancellationExecute(executor,
|
|
8997
|
+
function cancellationExecute(executor, resolve3, reject2) {
|
|
8998
8998
|
var promise = this;
|
|
8999
8999
|
try {
|
|
9000
|
-
executor(
|
|
9000
|
+
executor(resolve3, reject2, function(onCancel) {
|
|
9001
9001
|
if (typeof onCancel !== "function") {
|
|
9002
9002
|
throw new TypeError("onCancel must be a function, got: " + util2.toString(onCancel));
|
|
9003
9003
|
}
|
|
@@ -12644,14 +12644,14 @@ var require_promises = __commonJS({
|
|
|
12644
12644
|
});
|
|
12645
12645
|
};
|
|
12646
12646
|
function defer() {
|
|
12647
|
-
var
|
|
12647
|
+
var resolve3;
|
|
12648
12648
|
var reject2;
|
|
12649
12649
|
var promise = new bluebird.Promise(function(resolveArg, rejectArg) {
|
|
12650
|
-
|
|
12650
|
+
resolve3 = resolveArg;
|
|
12651
12651
|
reject2 = rejectArg;
|
|
12652
12652
|
});
|
|
12653
12653
|
return {
|
|
12654
|
-
resolve:
|
|
12654
|
+
resolve: resolve3,
|
|
12655
12655
|
reject: reject2,
|
|
12656
12656
|
promise
|
|
12657
12657
|
};
|
|
@@ -15325,8 +15325,8 @@ var require_lib2 = __commonJS({
|
|
|
15325
15325
|
return this;
|
|
15326
15326
|
}
|
|
15327
15327
|
var p = this.constructor;
|
|
15328
|
-
return this.then(
|
|
15329
|
-
function
|
|
15328
|
+
return this.then(resolve4, reject3);
|
|
15329
|
+
function resolve4(value) {
|
|
15330
15330
|
function yes() {
|
|
15331
15331
|
return value;
|
|
15332
15332
|
}
|
|
@@ -15479,8 +15479,8 @@ var require_lib2 = __commonJS({
|
|
|
15479
15479
|
}
|
|
15480
15480
|
return out;
|
|
15481
15481
|
}
|
|
15482
|
-
Promise2.resolve =
|
|
15483
|
-
function
|
|
15482
|
+
Promise2.resolve = resolve3;
|
|
15483
|
+
function resolve3(value) {
|
|
15484
15484
|
if (value instanceof this) {
|
|
15485
15485
|
return value;
|
|
15486
15486
|
}
|
|
@@ -16012,10 +16012,10 @@ var require_utils = __commonJS({
|
|
|
16012
16012
|
var promise = external.Promise.resolve(inputData).then(function(data) {
|
|
16013
16013
|
var isBlob = support.blob && (data instanceof Blob || ["[object File]", "[object Blob]"].indexOf(Object.prototype.toString.call(data)) !== -1);
|
|
16014
16014
|
if (isBlob && typeof FileReader !== "undefined") {
|
|
16015
|
-
return new external.Promise(function(
|
|
16015
|
+
return new external.Promise(function(resolve3, reject2) {
|
|
16016
16016
|
var reader = new FileReader();
|
|
16017
16017
|
reader.onload = function(e) {
|
|
16018
|
-
|
|
16018
|
+
resolve3(e.target.result);
|
|
16019
16019
|
};
|
|
16020
16020
|
reader.onerror = function(e) {
|
|
16021
16021
|
reject2(e.target.error);
|
|
@@ -16570,7 +16570,7 @@ var require_StreamHelper = __commonJS({
|
|
|
16570
16570
|
}
|
|
16571
16571
|
}
|
|
16572
16572
|
function accumulate(helper, updateCallback) {
|
|
16573
|
-
return new external.Promise(function(
|
|
16573
|
+
return new external.Promise(function(resolve3, reject2) {
|
|
16574
16574
|
var dataArray = [];
|
|
16575
16575
|
var chunkType = helper._internalType, resultType = helper._outputType, mimeType = helper._mimeType;
|
|
16576
16576
|
helper.on("data", function(data, meta2) {
|
|
@@ -16584,7 +16584,7 @@ var require_StreamHelper = __commonJS({
|
|
|
16584
16584
|
}).on("end", function() {
|
|
16585
16585
|
try {
|
|
16586
16586
|
var result2 = transformZipOutput(resultType, concat(chunkType, dataArray), mimeType);
|
|
16587
|
-
|
|
16587
|
+
resolve3(result2);
|
|
16588
16588
|
} catch (e) {
|
|
16589
16589
|
reject2(e);
|
|
16590
16590
|
}
|
|
@@ -22697,7 +22697,7 @@ var require_load = __commonJS({
|
|
|
22697
22697
|
var Crc32Probe = require_Crc32Probe();
|
|
22698
22698
|
var nodejsUtils = require_nodejsUtils();
|
|
22699
22699
|
function checkEntryCRC32(zipEntry) {
|
|
22700
|
-
return new external.Promise(function(
|
|
22700
|
+
return new external.Promise(function(resolve3, reject2) {
|
|
22701
22701
|
var worker = zipEntry.decompressed.getContentWorker().pipe(new Crc32Probe());
|
|
22702
22702
|
worker.on("error", function(e) {
|
|
22703
22703
|
reject2(e);
|
|
@@ -22705,7 +22705,7 @@ var require_load = __commonJS({
|
|
|
22705
22705
|
if (worker.streamInfo.crc32 !== zipEntry.decompressed.crc32) {
|
|
22706
22706
|
reject2(new Error("Corrupted zip : CRC32 mismatch"));
|
|
22707
22707
|
} else {
|
|
22708
|
-
|
|
22708
|
+
resolve3();
|
|
22709
22709
|
}
|
|
22710
22710
|
}).resume();
|
|
22711
22711
|
});
|
|
@@ -32473,7 +32473,7 @@ var require_files = __commonJS({
|
|
|
32473
32473
|
var fs9 = __require("fs");
|
|
32474
32474
|
var url = __require("url");
|
|
32475
32475
|
var os2 = __require("os");
|
|
32476
|
-
var
|
|
32476
|
+
var dirname4 = __require("path").dirname;
|
|
32477
32477
|
var resolvePath = __require("path").resolve;
|
|
32478
32478
|
var isAbsolutePath = require_path_is_absolute();
|
|
32479
32479
|
var promises = require_promises();
|
|
@@ -32488,7 +32488,7 @@ var require_files = __commonJS({
|
|
|
32488
32488
|
}
|
|
32489
32489
|
};
|
|
32490
32490
|
}
|
|
32491
|
-
var base = options.relativeToFile ?
|
|
32491
|
+
var base = options.relativeToFile ? dirname4(options.relativeToFile) : null;
|
|
32492
32492
|
function read(uri, encoding) {
|
|
32493
32493
|
return resolveUri(uri).then(function(path13) {
|
|
32494
32494
|
return readFile(path13, encoding).caught(function(error2) {
|
|
@@ -36917,17 +36917,17 @@ var init_yjs = __esm({
|
|
|
36917
36917
|
this.isLoaded = false;
|
|
36918
36918
|
this.isSynced = false;
|
|
36919
36919
|
this.isDestroyed = false;
|
|
36920
|
-
this.whenLoaded = create5((
|
|
36920
|
+
this.whenLoaded = create5((resolve3) => {
|
|
36921
36921
|
this.on("load", () => {
|
|
36922
36922
|
this.isLoaded = true;
|
|
36923
|
-
|
|
36923
|
+
resolve3(this);
|
|
36924
36924
|
});
|
|
36925
36925
|
});
|
|
36926
|
-
const provideSyncedPromise = () => create5((
|
|
36926
|
+
const provideSyncedPromise = () => create5((resolve3) => {
|
|
36927
36927
|
const eventHandler = (isSynced) => {
|
|
36928
36928
|
if (isSynced === void 0 || isSynced === true) {
|
|
36929
36929
|
this.off("sync", eventHandler);
|
|
36930
|
-
|
|
36930
|
+
resolve3();
|
|
36931
36931
|
}
|
|
36932
36932
|
};
|
|
36933
36933
|
this.on("sync", eventHandler);
|
|
@@ -49050,10 +49050,10 @@ function resolveAll(constructs2, events, context) {
|
|
|
49050
49050
|
const called = [];
|
|
49051
49051
|
let index2 = -1;
|
|
49052
49052
|
while (++index2 < constructs2.length) {
|
|
49053
|
-
const
|
|
49054
|
-
if (
|
|
49055
|
-
events =
|
|
49056
|
-
called.push(
|
|
49053
|
+
const resolve3 = constructs2[index2].resolveAll;
|
|
49054
|
+
if (resolve3 && !called.includes(resolve3)) {
|
|
49055
|
+
events = resolve3(events, context);
|
|
49056
|
+
called.push(resolve3);
|
|
49057
49057
|
}
|
|
49058
49058
|
}
|
|
49059
49059
|
return events;
|
|
@@ -55684,10 +55684,10 @@ var init_lib21 = __esm({
|
|
|
55684
55684
|
* @returns {undefined}
|
|
55685
55685
|
* Nothing.
|
|
55686
55686
|
*/
|
|
55687
|
-
set basename(
|
|
55688
|
-
assertNonEmpty(
|
|
55689
|
-
assertPart(
|
|
55690
|
-
this.path = default2.join(this.dirname || "",
|
|
55687
|
+
set basename(basename2) {
|
|
55688
|
+
assertNonEmpty(basename2, "basename");
|
|
55689
|
+
assertPart(basename2, "basename");
|
|
55690
|
+
this.path = default2.join(this.dirname || "", basename2);
|
|
55691
55691
|
}
|
|
55692
55692
|
/**
|
|
55693
55693
|
* Get the parent path (example: `'~'`).
|
|
@@ -55708,9 +55708,9 @@ var init_lib21 = __esm({
|
|
|
55708
55708
|
* @returns {undefined}
|
|
55709
55709
|
* Nothing.
|
|
55710
55710
|
*/
|
|
55711
|
-
set dirname(
|
|
55711
|
+
set dirname(dirname4) {
|
|
55712
55712
|
assertPath(this.basename, "dirname");
|
|
55713
|
-
this.path = default2.join(
|
|
55713
|
+
this.path = default2.join(dirname4 || "", this.basename);
|
|
55714
55714
|
}
|
|
55715
55715
|
/**
|
|
55716
55716
|
* Get the extname (including dot) (example: `'.js'`).
|
|
@@ -56357,7 +56357,7 @@ var init_lib22 = __esm({
|
|
|
56357
56357
|
assertParser("process", this.parser || this.Parser);
|
|
56358
56358
|
assertCompiler("process", this.compiler || this.Compiler);
|
|
56359
56359
|
return done ? executor(void 0, done) : new Promise(executor);
|
|
56360
|
-
function executor(
|
|
56360
|
+
function executor(resolve3, reject2) {
|
|
56361
56361
|
const realFile = vfile(file);
|
|
56362
56362
|
const parseTree = (
|
|
56363
56363
|
/** @type {HeadTree extends undefined ? Node : HeadTree} */
|
|
@@ -56388,8 +56388,8 @@ var init_lib22 = __esm({
|
|
|
56388
56388
|
function realDone(error2, file2) {
|
|
56389
56389
|
if (error2 || !file2) {
|
|
56390
56390
|
reject2(error2);
|
|
56391
|
-
} else if (
|
|
56392
|
-
|
|
56391
|
+
} else if (resolve3) {
|
|
56392
|
+
resolve3(file2);
|
|
56393
56393
|
} else {
|
|
56394
56394
|
ok(done, "`done` is defined if `resolve` is not");
|
|
56395
56395
|
done(void 0, file2);
|
|
@@ -56491,7 +56491,7 @@ var init_lib22 = __esm({
|
|
|
56491
56491
|
file = void 0;
|
|
56492
56492
|
}
|
|
56493
56493
|
return done ? executor(void 0, done) : new Promise(executor);
|
|
56494
|
-
function executor(
|
|
56494
|
+
function executor(resolve3, reject2) {
|
|
56495
56495
|
ok(
|
|
56496
56496
|
typeof file !== "function",
|
|
56497
56497
|
"`file` can\u2019t be a `done` anymore, we checked"
|
|
@@ -56505,8 +56505,8 @@ var init_lib22 = __esm({
|
|
|
56505
56505
|
);
|
|
56506
56506
|
if (error2) {
|
|
56507
56507
|
reject2(error2);
|
|
56508
|
-
} else if (
|
|
56509
|
-
|
|
56508
|
+
} else if (resolve3) {
|
|
56509
|
+
resolve3(resultingTree);
|
|
56510
56510
|
} else {
|
|
56511
56511
|
ok(done, "`done` is defined if `resolve` is not");
|
|
56512
56512
|
done(void 0, resultingTree, file2);
|
|
@@ -60817,8 +60817,8 @@ var require_lib7 = __commonJS({
|
|
|
60817
60817
|
if (typeof cb2 !== "function") {
|
|
60818
60818
|
opts = cb2;
|
|
60819
60819
|
cb2 = null;
|
|
60820
|
-
deferred = new this.Promise(function(
|
|
60821
|
-
deferredResolve =
|
|
60820
|
+
deferred = new this.Promise(function(resolve3, reject2) {
|
|
60821
|
+
deferredResolve = resolve3;
|
|
60822
60822
|
deferredReject = reject2;
|
|
60823
60823
|
});
|
|
60824
60824
|
}
|
|
@@ -60966,17 +60966,17 @@ var require_lib7 = __commonJS({
|
|
|
60966
60966
|
if (typeof cb2 === "function") {
|
|
60967
60967
|
fnx(cb2);
|
|
60968
60968
|
} else {
|
|
60969
|
-
return new this.Promise(function(
|
|
60969
|
+
return new this.Promise(function(resolve3, reject2) {
|
|
60970
60970
|
if (fnx.length === 1) {
|
|
60971
60971
|
fnx(function(err, ret2) {
|
|
60972
60972
|
if (err) {
|
|
60973
60973
|
reject2(err);
|
|
60974
60974
|
} else {
|
|
60975
|
-
|
|
60975
|
+
resolve3(ret2);
|
|
60976
60976
|
}
|
|
60977
60977
|
});
|
|
60978
60978
|
} else {
|
|
60979
|
-
|
|
60979
|
+
resolve3(fnx());
|
|
60980
60980
|
}
|
|
60981
60981
|
});
|
|
60982
60982
|
}
|
|
@@ -66737,7 +66737,7 @@ var init_hocuspocus_server_esm = __esm({
|
|
|
66737
66737
|
process.on("SIGQUIT", signalHandler);
|
|
66738
66738
|
process.on("SIGTERM", signalHandler);
|
|
66739
66739
|
}
|
|
66740
|
-
return new Promise((
|
|
66740
|
+
return new Promise((resolve3, reject2) => {
|
|
66741
66741
|
var _a;
|
|
66742
66742
|
(_a = this.server) === null || _a === void 0 ? void 0 : _a.httpServer.listen({
|
|
66743
66743
|
port: this.configuration.port,
|
|
@@ -66753,7 +66753,7 @@ var init_hocuspocus_server_esm = __esm({
|
|
|
66753
66753
|
};
|
|
66754
66754
|
try {
|
|
66755
66755
|
await this.hooks("onListen", onListenPayload);
|
|
66756
|
-
|
|
66756
|
+
resolve3(this);
|
|
66757
66757
|
} catch (e) {
|
|
66758
66758
|
reject2(e);
|
|
66759
66759
|
}
|
|
@@ -66837,19 +66837,19 @@ var init_hocuspocus_server_esm = __esm({
|
|
|
66837
66837
|
* Destroy the server
|
|
66838
66838
|
*/
|
|
66839
66839
|
async destroy() {
|
|
66840
|
-
await new Promise(async (
|
|
66840
|
+
await new Promise(async (resolve3) => {
|
|
66841
66841
|
var _a, _b, _c, _d;
|
|
66842
66842
|
(_b = (_a = this.server) === null || _a === void 0 ? void 0 : _a.httpServer) === null || _b === void 0 ? void 0 : _b.close();
|
|
66843
66843
|
try {
|
|
66844
66844
|
this.configuration.extensions.push({
|
|
66845
66845
|
async afterUnloadDocument({ instance }) {
|
|
66846
66846
|
if (instance.getDocumentsCount() === 0)
|
|
66847
|
-
|
|
66847
|
+
resolve3("");
|
|
66848
66848
|
}
|
|
66849
66849
|
});
|
|
66850
66850
|
(_d = (_c = this.server) === null || _c === void 0 ? void 0 : _c.webSocketServer) === null || _d === void 0 ? void 0 : _d.close();
|
|
66851
66851
|
if (this.getDocumentsCount() === 0)
|
|
66852
|
-
|
|
66852
|
+
resolve3("");
|
|
66853
66853
|
this.closeConnections();
|
|
66854
66854
|
} catch (error2) {
|
|
66855
66855
|
console.error(error2);
|
|
@@ -67314,19 +67314,19 @@ async function waitForPort(port, timeoutMs = 5e3) {
|
|
|
67314
67314
|
throw new Error(`Port ${port} still not available after ${timeoutMs}ms`);
|
|
67315
67315
|
}
|
|
67316
67316
|
function tryBind(port) {
|
|
67317
|
-
return new Promise((
|
|
67317
|
+
return new Promise((resolve3, reject2) => {
|
|
67318
67318
|
const srv = net.createServer();
|
|
67319
67319
|
srv.once("error", (err) => {
|
|
67320
67320
|
srv.close(() => {
|
|
67321
67321
|
if (err.code === "EADDRINUSE") {
|
|
67322
|
-
|
|
67322
|
+
resolve3(false);
|
|
67323
67323
|
} else {
|
|
67324
67324
|
reject2(err);
|
|
67325
67325
|
}
|
|
67326
67326
|
});
|
|
67327
67327
|
});
|
|
67328
67328
|
srv.listen(port, "127.0.0.1", () => {
|
|
67329
|
-
srv.close(() =>
|
|
67329
|
+
srv.close(() => resolve3(true));
|
|
67330
67330
|
});
|
|
67331
67331
|
});
|
|
67332
67332
|
}
|
|
@@ -75970,10 +75970,10 @@ var require_raw_body = __commonJS({
|
|
|
75970
75970
|
if (done) {
|
|
75971
75971
|
return readStream(stream, encoding, length3, limit, wrap3(done));
|
|
75972
75972
|
}
|
|
75973
|
-
return new Promise(function executor(
|
|
75973
|
+
return new Promise(function executor(resolve3, reject2) {
|
|
75974
75974
|
readStream(stream, encoding, length3, limit, function onRead(err, buf) {
|
|
75975
75975
|
if (err) return reject2(err);
|
|
75976
|
-
|
|
75976
|
+
resolve3(buf);
|
|
75977
75977
|
});
|
|
75978
75978
|
});
|
|
75979
75979
|
}
|
|
@@ -89309,11 +89309,11 @@ var require_view = __commonJS({
|
|
|
89309
89309
|
var debug = require_src()("express:view");
|
|
89310
89310
|
var path13 = __require("path");
|
|
89311
89311
|
var fs9 = __require("fs");
|
|
89312
|
-
var
|
|
89313
|
-
var
|
|
89312
|
+
var dirname4 = path13.dirname;
|
|
89313
|
+
var basename2 = path13.basename;
|
|
89314
89314
|
var extname = path13.extname;
|
|
89315
89315
|
var join4 = path13.join;
|
|
89316
|
-
var
|
|
89316
|
+
var resolve3 = path13.resolve;
|
|
89317
89317
|
module3.exports = View;
|
|
89318
89318
|
function View(name2, options) {
|
|
89319
89319
|
var opts = options || {};
|
|
@@ -89347,9 +89347,9 @@ var require_view = __commonJS({
|
|
|
89347
89347
|
debug('lookup "%s"', name2);
|
|
89348
89348
|
for (var i = 0; i < roots.length && !path14; i++) {
|
|
89349
89349
|
var root3 = roots[i];
|
|
89350
|
-
var loc =
|
|
89351
|
-
var dir =
|
|
89352
|
-
var file =
|
|
89350
|
+
var loc = resolve3(root3, name2);
|
|
89351
|
+
var dir = dirname4(loc);
|
|
89352
|
+
var file = basename2(loc);
|
|
89353
89353
|
path14 = this.resolve(dir, file);
|
|
89354
89354
|
}
|
|
89355
89355
|
return path14;
|
|
@@ -89372,14 +89372,14 @@ var require_view = __commonJS({
|
|
|
89372
89372
|
});
|
|
89373
89373
|
sync = false;
|
|
89374
89374
|
};
|
|
89375
|
-
View.prototype.resolve = function
|
|
89375
|
+
View.prototype.resolve = function resolve4(dir, file) {
|
|
89376
89376
|
var ext = this.ext;
|
|
89377
89377
|
var path14 = join4(dir, file);
|
|
89378
89378
|
var stat = tryStat(path14);
|
|
89379
89379
|
if (stat && stat.isFile()) {
|
|
89380
89380
|
return path14;
|
|
89381
89381
|
}
|
|
89382
|
-
path14 = join4(dir,
|
|
89382
|
+
path14 = join4(dir, basename2(file, ext), "index" + ext);
|
|
89383
89383
|
stat = tryStat(path14);
|
|
89384
89384
|
if (stat && stat.isFile()) {
|
|
89385
89385
|
return path14;
|
|
@@ -91555,7 +91555,7 @@ var require_application = __commonJS({
|
|
|
91555
91555
|
var compileETag = require_utils4().compileETag;
|
|
91556
91556
|
var compileQueryParser = require_utils4().compileQueryParser;
|
|
91557
91557
|
var compileTrust = require_utils4().compileTrust;
|
|
91558
|
-
var
|
|
91558
|
+
var resolve3 = __require("path").resolve;
|
|
91559
91559
|
var once = require_once();
|
|
91560
91560
|
var Router = require_router();
|
|
91561
91561
|
var slice2 = Array.prototype.slice;
|
|
@@ -91609,7 +91609,7 @@ var require_application = __commonJS({
|
|
|
91609
91609
|
this.mountpath = "/";
|
|
91610
91610
|
this.locals.settings = this.settings;
|
|
91611
91611
|
this.set("view", View);
|
|
91612
|
-
this.set("views",
|
|
91612
|
+
this.set("views", resolve3("views"));
|
|
91613
91613
|
this.set("jsonp callback name", "callback");
|
|
91614
91614
|
if (env3 === "production") {
|
|
91615
91615
|
this.enable("view cache");
|
|
@@ -92705,7 +92705,7 @@ var require_content_disposition = __commonJS({
|
|
|
92705
92705
|
"use strict";
|
|
92706
92706
|
module3.exports = contentDisposition;
|
|
92707
92707
|
module3.exports.parse = parse4;
|
|
92708
|
-
var
|
|
92708
|
+
var basename2 = __require("path").basename;
|
|
92709
92709
|
var ENCODE_URL_ATTR_CHAR_REGEXP = /[\x00-\x20"'()*,/:;<=>?@[\\\]{}\x7f]/g;
|
|
92710
92710
|
var HEX_ESCAPE_REGEXP = /%[0-9A-Fa-f]{2}/;
|
|
92711
92711
|
var HEX_ESCAPE_REPLACE_REGEXP = /%([0-9A-Fa-f]{2})/g;
|
|
@@ -92740,9 +92740,9 @@ var require_content_disposition = __commonJS({
|
|
|
92740
92740
|
if (typeof fallback === "string" && NON_LATIN1_REGEXP.test(fallback)) {
|
|
92741
92741
|
throw new TypeError("fallback must be ISO-8859-1 string");
|
|
92742
92742
|
}
|
|
92743
|
-
var name2 =
|
|
92743
|
+
var name2 = basename2(filename);
|
|
92744
92744
|
var isQuotedString = TEXT_REGEXP.test(name2);
|
|
92745
|
-
var fallbackName = typeof fallback !== "string" ? fallback && getlatin1(name2) :
|
|
92745
|
+
var fallbackName = typeof fallback !== "string" ? fallback && getlatin1(name2) : basename2(fallback);
|
|
92746
92746
|
var hasFallback = typeof fallbackName === "string" && fallbackName !== name2;
|
|
92747
92747
|
if (hasFallback || !isQuotedString || HEX_ESCAPE_REGEXP.test(name2)) {
|
|
92748
92748
|
params2["filename*"] = name2;
|
|
@@ -93069,7 +93069,7 @@ var require_send = __commonJS({
|
|
|
93069
93069
|
var extname = path13.extname;
|
|
93070
93070
|
var join4 = path13.join;
|
|
93071
93071
|
var normalize = path13.normalize;
|
|
93072
|
-
var
|
|
93072
|
+
var resolve3 = path13.resolve;
|
|
93073
93073
|
var sep = path13.sep;
|
|
93074
93074
|
var BYTES_RANGE_REGEXP = /^ *bytes=/;
|
|
93075
93075
|
var MAX_MAXAGE = 60 * 60 * 24 * 365 * 1e3;
|
|
@@ -93098,7 +93098,7 @@ var require_send = __commonJS({
|
|
|
93098
93098
|
this._maxage = opts.maxAge || opts.maxage;
|
|
93099
93099
|
this._maxage = typeof this._maxage === "string" ? ms(this._maxage) : Number(this._maxage);
|
|
93100
93100
|
this._maxage = !isNaN(this._maxage) ? Math.min(Math.max(0, this._maxage), MAX_MAXAGE) : 0;
|
|
93101
|
-
this._root = opts.root ?
|
|
93101
|
+
this._root = opts.root ? resolve3(opts.root) : null;
|
|
93102
93102
|
}
|
|
93103
93103
|
util2.inherits(SendStream, Stream);
|
|
93104
93104
|
SendStream.prototype.error = function error2(status, err) {
|
|
@@ -93247,7 +93247,7 @@ var require_send = __commonJS({
|
|
|
93247
93247
|
return res;
|
|
93248
93248
|
}
|
|
93249
93249
|
parts = normalize(path14).split(sep);
|
|
93250
|
-
path14 =
|
|
93250
|
+
path14 = resolve3(path14);
|
|
93251
93251
|
}
|
|
93252
93252
|
if (containsDotFile(parts)) {
|
|
93253
93253
|
debug('%s dotfile "%s"', this._dotfiles, path14);
|
|
@@ -93625,7 +93625,7 @@ var require_response = __commonJS({
|
|
|
93625
93625
|
var cookie = require_cookie();
|
|
93626
93626
|
var send = require_send();
|
|
93627
93627
|
var extname = path13.extname;
|
|
93628
|
-
var
|
|
93628
|
+
var resolve3 = path13.resolve;
|
|
93629
93629
|
var vary = require_vary();
|
|
93630
93630
|
var { Buffer: Buffer2 } = __require("buffer");
|
|
93631
93631
|
var res = Object.create(http.ServerResponse.prototype);
|
|
@@ -93831,7 +93831,7 @@ var require_response = __commonJS({
|
|
|
93831
93831
|
}
|
|
93832
93832
|
opts = Object.create(opts);
|
|
93833
93833
|
opts.headers = headers;
|
|
93834
|
-
var fullPath = !opts.root ?
|
|
93834
|
+
var fullPath = !opts.root ? resolve3(path14) : path14;
|
|
93835
93835
|
return this.sendFile(fullPath, opts, done);
|
|
93836
93836
|
};
|
|
93837
93837
|
res.contentType = res.type = function contentType(type2) {
|
|
@@ -94080,7 +94080,7 @@ var require_serve_static = __commonJS({
|
|
|
94080
94080
|
var encodeUrl = require_encodeurl();
|
|
94081
94081
|
var escapeHtml = require_escape_html();
|
|
94082
94082
|
var parseUrl = require_parseurl();
|
|
94083
|
-
var
|
|
94083
|
+
var resolve3 = __require("path").resolve;
|
|
94084
94084
|
var send = require_send();
|
|
94085
94085
|
var url = __require("url");
|
|
94086
94086
|
module3.exports = serveStatic;
|
|
@@ -94099,7 +94099,7 @@ var require_serve_static = __commonJS({
|
|
|
94099
94099
|
throw new TypeError("option setHeaders must be function");
|
|
94100
94100
|
}
|
|
94101
94101
|
opts.maxage = opts.maxage || opts.maxAge || 0;
|
|
94102
|
-
opts.root =
|
|
94102
|
+
opts.root = resolve3(root3);
|
|
94103
94103
|
var onDirectory = redirect ? createRedirectDirectoryListener() : createNotFoundDirectoryListener();
|
|
94104
94104
|
return function serveStatic2(req, res, next) {
|
|
94105
94105
|
if (req.method !== "GET" && req.method !== "HEAD") {
|
|
@@ -97176,7 +97176,7 @@ var require_compile = __commonJS({
|
|
|
97176
97176
|
const schOrFunc = root3.refs[ref];
|
|
97177
97177
|
if (schOrFunc)
|
|
97178
97178
|
return schOrFunc;
|
|
97179
|
-
let _sch =
|
|
97179
|
+
let _sch = resolve3.call(this, root3, ref);
|
|
97180
97180
|
if (_sch === void 0) {
|
|
97181
97181
|
const schema = (_a = root3.localRefs) === null || _a === void 0 ? void 0 : _a[ref];
|
|
97182
97182
|
const { schemaId } = this.opts;
|
|
@@ -97203,7 +97203,7 @@ var require_compile = __commonJS({
|
|
|
97203
97203
|
function sameSchemaEnv(s1, s2) {
|
|
97204
97204
|
return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
|
|
97205
97205
|
}
|
|
97206
|
-
function
|
|
97206
|
+
function resolve3(root3, ref) {
|
|
97207
97207
|
let sch;
|
|
97208
97208
|
while (typeof (sch = this.refs[ref]) == "string")
|
|
97209
97209
|
ref = sch;
|
|
@@ -97778,7 +97778,7 @@ var require_fast_uri = __commonJS({
|
|
|
97778
97778
|
}
|
|
97779
97779
|
return uri;
|
|
97780
97780
|
}
|
|
97781
|
-
function
|
|
97781
|
+
function resolve3(baseURI, relativeURI, options) {
|
|
97782
97782
|
const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
|
|
97783
97783
|
const resolved = resolveComponent(parse4(baseURI, schemelessOptions), parse4(relativeURI, schemelessOptions), schemelessOptions, true);
|
|
97784
97784
|
schemelessOptions.skipEscape = true;
|
|
@@ -98005,7 +98005,7 @@ var require_fast_uri = __commonJS({
|
|
|
98005
98005
|
var fastUri = {
|
|
98006
98006
|
SCHEMES,
|
|
98007
98007
|
normalize,
|
|
98008
|
-
resolve:
|
|
98008
|
+
resolve: resolve3,
|
|
98009
98009
|
resolveComponent,
|
|
98010
98010
|
equal,
|
|
98011
98011
|
serialize: serialize2,
|
|
@@ -101086,7 +101086,7 @@ var init_launcher = __esm({
|
|
|
101086
101086
|
// src/server/index.ts
|
|
101087
101087
|
init_constants();
|
|
101088
101088
|
import path12 from "path";
|
|
101089
|
-
import { fileURLToPath as
|
|
101089
|
+
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
101090
101090
|
|
|
101091
101091
|
// src/server/error-filter.ts
|
|
101092
101092
|
function isKnownHocuspocusError(err) {
|
|
@@ -101114,8 +101114,8 @@ init_file_opener();
|
|
|
101114
101114
|
|
|
101115
101115
|
// src/server/mcp/server.ts
|
|
101116
101116
|
import { existsSync as existsSync2 } from "fs";
|
|
101117
|
-
import { dirname as
|
|
101118
|
-
import { fileURLToPath as
|
|
101117
|
+
import { dirname as dirname3, join as join3 } from "path";
|
|
101118
|
+
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
101119
101119
|
|
|
101120
101120
|
// node_modules/@modelcontextprotocol/sdk/dist/esm/server/express.js
|
|
101121
101121
|
var import_express = __toESM(require_express2(), 1);
|
|
@@ -109218,7 +109218,7 @@ var Protocol = class {
|
|
|
109218
109218
|
return;
|
|
109219
109219
|
}
|
|
109220
109220
|
const pollInterval = task2.pollInterval ?? this._options?.defaultTaskPollInterval ?? 1e3;
|
|
109221
|
-
await new Promise((
|
|
109221
|
+
await new Promise((resolve3) => setTimeout(resolve3, pollInterval));
|
|
109222
109222
|
options?.signal?.throwIfAborted();
|
|
109223
109223
|
}
|
|
109224
109224
|
} catch (error2) {
|
|
@@ -109235,7 +109235,7 @@ var Protocol = class {
|
|
|
109235
109235
|
*/
|
|
109236
109236
|
request(request, resultSchema, options) {
|
|
109237
109237
|
const { relatedRequestId, resumptionToken, onresumptiontoken, task, relatedTask } = options ?? {};
|
|
109238
|
-
return new Promise((
|
|
109238
|
+
return new Promise((resolve3, reject2) => {
|
|
109239
109239
|
const earlyReject = (error2) => {
|
|
109240
109240
|
reject2(error2);
|
|
109241
109241
|
};
|
|
@@ -109313,7 +109313,7 @@ var Protocol = class {
|
|
|
109313
109313
|
if (!parseResult.success) {
|
|
109314
109314
|
reject2(parseResult.error);
|
|
109315
109315
|
} else {
|
|
109316
|
-
|
|
109316
|
+
resolve3(parseResult.data);
|
|
109317
109317
|
}
|
|
109318
109318
|
} catch (error2) {
|
|
109319
109319
|
reject2(error2);
|
|
@@ -109574,12 +109574,12 @@ var Protocol = class {
|
|
|
109574
109574
|
}
|
|
109575
109575
|
} catch {
|
|
109576
109576
|
}
|
|
109577
|
-
return new Promise((
|
|
109577
|
+
return new Promise((resolve3, reject2) => {
|
|
109578
109578
|
if (signal.aborted) {
|
|
109579
109579
|
reject2(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
|
|
109580
109580
|
return;
|
|
109581
109581
|
}
|
|
109582
|
-
const timeoutId = setTimeout(
|
|
109582
|
+
const timeoutId = setTimeout(resolve3, interval);
|
|
109583
109583
|
signal.addEventListener("abort", () => {
|
|
109584
109584
|
clearTimeout(timeoutId);
|
|
109585
109585
|
reject2(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
|
|
@@ -110680,7 +110680,7 @@ var McpServer = class {
|
|
|
110680
110680
|
let task = createTaskResult.task;
|
|
110681
110681
|
const pollInterval = task.pollInterval ?? 5e3;
|
|
110682
110682
|
while (task.status !== "completed" && task.status !== "failed" && task.status !== "cancelled") {
|
|
110683
|
-
await new Promise((
|
|
110683
|
+
await new Promise((resolve3) => setTimeout(resolve3, pollInterval));
|
|
110684
110684
|
const updatedTask = await extra.taskStore.getTask(taskId);
|
|
110685
110685
|
if (!updatedTask) {
|
|
110686
110686
|
throw new McpError(ErrorCode.InternalError, `Task ${taskId} not found during polling`);
|
|
@@ -111323,12 +111323,12 @@ var StdioServerTransport = class {
|
|
|
111323
111323
|
this.onclose?.();
|
|
111324
111324
|
}
|
|
111325
111325
|
send(message) {
|
|
111326
|
-
return new Promise((
|
|
111326
|
+
return new Promise((resolve3) => {
|
|
111327
111327
|
const json = serializeMessage(message);
|
|
111328
111328
|
if (this._stdout.write(json)) {
|
|
111329
|
-
|
|
111329
|
+
resolve3();
|
|
111330
111330
|
} else {
|
|
111331
|
-
this._stdout.once("drain",
|
|
111331
|
+
this._stdout.once("drain", resolve3);
|
|
111332
111332
|
}
|
|
111333
111333
|
});
|
|
111334
111334
|
}
|
|
@@ -111805,7 +111805,7 @@ var responseViaResponseObject = async (res, outgoing, options = {}) => {
|
|
|
111805
111805
|
});
|
|
111806
111806
|
if (!chunk2) {
|
|
111807
111807
|
if (i === 1) {
|
|
111808
|
-
await new Promise((
|
|
111808
|
+
await new Promise((resolve3) => setTimeout(resolve3));
|
|
111809
111809
|
maxReadCount = 3;
|
|
111810
111810
|
continue;
|
|
111811
111811
|
}
|
|
@@ -112305,9 +112305,9 @@ data:
|
|
|
112305
112305
|
const initRequest = messages.find((m) => isInitializeRequest(m));
|
|
112306
112306
|
const clientProtocolVersion = initRequest ? initRequest.params.protocolVersion : req.headers.get("mcp-protocol-version") ?? DEFAULT_NEGOTIATED_PROTOCOL_VERSION;
|
|
112307
112307
|
if (this._enableJsonResponse) {
|
|
112308
|
-
return new Promise((
|
|
112308
|
+
return new Promise((resolve3) => {
|
|
112309
112309
|
this._streamMapping.set(streamId, {
|
|
112310
|
-
resolveJson:
|
|
112310
|
+
resolveJson: resolve3,
|
|
112311
112311
|
cleanup: () => {
|
|
112312
112312
|
this._streamMapping.delete(streamId);
|
|
112313
112313
|
}
|
|
@@ -112670,124 +112670,37 @@ init_annotations();
|
|
|
112670
112670
|
// src/cli/setup.ts
|
|
112671
112671
|
init_constants();
|
|
112672
112672
|
import { randomUUID as randomUUID4 } from "crypto";
|
|
112673
|
-
import { existsSync, readFileSync } from "fs";
|
|
112673
|
+
import { existsSync, readFileSync as readFileSync2 } from "fs";
|
|
112674
112674
|
import { copyFile, mkdir, rename, unlink, writeFile } from "fs/promises";
|
|
112675
112675
|
import { homedir as homedir2 } from "os";
|
|
112676
|
-
import { dirname, join as join2, resolve } from "path";
|
|
112677
|
-
import { fileURLToPath as
|
|
112676
|
+
import { basename, dirname as dirname2, join as join2, resolve as resolve2 } from "path";
|
|
112677
|
+
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
112678
112678
|
|
|
112679
112679
|
// src/cli/skill-content.ts
|
|
112680
|
-
|
|
112681
|
-
|
|
112682
|
-
|
|
112683
|
-
|
|
112684
|
-
|
|
112685
|
-
|
|
112686
|
-
collaborative editor.
|
|
112687
|
-
---
|
|
112688
|
-
|
|
112689
|
-
# Tandem \u2014 Collaborative Document Editor
|
|
112690
|
-
|
|
112691
|
-
Tandem lets you annotate and edit documents alongside the user in real time. The user sees your changes in a browser editor; you interact via the tandem_* MCP tool suite.
|
|
112692
|
-
|
|
112693
|
-
## Hard Rules
|
|
112694
|
-
|
|
112695
|
-
These prevent the most common failures. Follow them always.
|
|
112696
|
-
|
|
112697
|
-
1. **Resolve before mutating.** Call \`tandem_resolveRange\` (or \`tandem_search\`) to get offsets before calling \`tandem_edit\`, \`tandem_highlight\`, \`tandem_comment\`, \`tandem_suggest\`, or \`tandem_flag\`. Never compute offsets by counting characters in previously-read text \u2014 they go stale when the user edits.
|
|
112698
|
-
2. **Pass \`textSnapshot\`.** Include the matched text as \`textSnapshot\` on mutations and annotations. If the text moved, the server returns \`RANGE_MOVED\` with relocated coordinates instead of corrupting the document.
|
|
112699
|
-
3. **Use \`tandem_getTextContent\`, not \`tandem_getContent\`.** \`getContent\` returns ProseMirror JSON and burns tokens. Use \`getTextContent({ section: "Section Name" })\` for targeted reads. The \`section\` parameter is case-insensitive.
|
|
112700
|
-
4. **\`tandem_edit\` cannot create paragraphs.** Newlines become literal characters. For multi-paragraph changes, use multiple \`tandem_edit\` calls or \`tandem_suggest\`.
|
|
112701
|
-
5. **\`.docx\` files are read-only.** Use annotations instead of \`tandem_edit\`. Offer \`tandem_convertToMarkdown\` if the user wants an editable copy.
|
|
112702
|
-
|
|
112703
|
-
## Workflow
|
|
112704
|
-
|
|
112705
|
-
Standard workflow:
|
|
112706
|
-
|
|
112707
|
-
1. \`tandem_status\` \u2014 check for already-open documents (sessions restore automatically)
|
|
112708
|
-
2. \`tandem_getOutline\` \u2014 understand document structure
|
|
112709
|
-
3. \`tandem_setStatus("Working on [section]...", { focusParagraph: N })\` \u2014 show progress (use \`index\` from outline)
|
|
112710
|
-
4. \`tandem_getTextContent({ section: "..." })\` \u2014 read one section at a time
|
|
112711
|
-
5. Annotate or edit as needed (see annotation guide below)
|
|
112712
|
-
6. \`tandem_checkInbox\` \u2014 check for user messages and actions
|
|
112713
|
-
7. Repeat steps 3-6 for each section
|
|
112714
|
-
8. \`tandem_save\` \u2014 persist edits to disk when done
|
|
112715
|
-
|
|
112716
|
-
## Annotation Guide
|
|
112717
|
-
|
|
112718
|
-
Choose the right type for each finding:
|
|
112719
|
-
|
|
112720
|
-
- **\`tandem_highlight\`** \u2014 Visual marker with a short note. Colors: green (verified/good), red (problem), yellow (needs attention). Use when the finding is self-evident from the color and a brief note.
|
|
112721
|
-
- **\`tandem_comment\`** \u2014 Observation requiring explanation. Use when you need more than one sentence to convey reasoning.
|
|
112722
|
-
- **\`tandem_suggest\`** \u2014 Specific text replacement. **Prefer over comment when you can provide replacement text** \u2014 the user gets one-click accept/reject. Cannot create new paragraphs.
|
|
112723
|
-
- **\`tandem_flag\`** \u2014 Factual errors, compliance risks, missing required content. Signals a blocking issue the user must address before the document ships.
|
|
112724
|
-
|
|
112725
|
-
**User-created types:** \`question\` annotation is created by users, not Claude. When you see a \`question\` in \`tandem_checkInbox\` or \`tandem_getAnnotations\`, respond with a \`tandem_comment\` on the same range or \`tandem_reply\` for conversational answers.
|
|
112726
|
-
|
|
112727
|
-
## Collaboration Mode
|
|
112728
|
-
|
|
112729
|
-
Check \`mode\` from \`tandem_status\` or \`tandem_checkInbox\` and adapt:
|
|
112730
|
-
|
|
112731
|
-
- **Tandem** (\`"tandem"\`, default) \u2014 Full collaboration. Annotate freely and react to selections and document changes.
|
|
112732
|
-
- **Solo** (\`"solo"\`) \u2014 The user wants to write undisturbed. Only respond when the user sends a chat message. Do not proactively annotate or react to document activity.
|
|
112733
|
-
|
|
112734
|
-
## Reacting to Document Events
|
|
112735
|
-
|
|
112736
|
-
Selections are **not** sent as standalone events. Instead, when the user sends a chat message, any buffered selection is attached as a \`selection\` field on the \`chat:message\` payload. This gives you context about what text the user was looking at when they wrote their message. When polling via \`tandem_checkInbox\`, the current selection shows up under \`activity.selectedText\`. Use \`tandem_reply\` for any document-context reaction (chat messages, question annotations); reserve terminal output for non-document work the user explicitly requests. In Solo mode, hold reactions until the user sends a chat message.
|
|
112737
|
-
|
|
112738
|
-
## Collaboration Etiquette
|
|
112739
|
-
|
|
112740
|
-
- Check \`tandem_getActivity()\` before annotating near the user's cursor. If \`isTyping\` is true, wait for typing to stop before annotating that area.
|
|
112741
|
-
- Use \`tandem_setStatus\` to show what you're working on \u2014 the user sees it in the browser status bar.
|
|
112742
|
-
- **Call \`tandem_checkInbox\` every 2-3 tool calls**, not just at the end of a task. The real-time channel is often not connected; polling is the reliable path.
|
|
112743
|
-
- Reply to chat messages with \`tandem_reply\`, not annotations.
|
|
112744
|
-
|
|
112745
|
-
## .docx Review Workflow
|
|
112746
|
-
|
|
112747
|
-
1. \`tandem_open\` \u2014 opens in read-only mode (\`readOnly: true\`)
|
|
112748
|
-
2. \`tandem_getAnnotations({ author: "import" })\` \u2014 check for imported Word comments; read and act on them
|
|
112749
|
-
3. Annotate with findings (highlight, comment, suggest, flag)
|
|
112750
|
-
4. \`tandem_exportAnnotations\` \u2014 generate a review summary the user can share
|
|
112751
|
-
5. If the user wants editable text, offer \`tandem_convertToMarkdown\`
|
|
112752
|
-
|
|
112753
|
-
## Error Recovery
|
|
112754
|
-
|
|
112755
|
-
- **\`RANGE_MOVED\`** \u2014 Text shifted since you read it. The response includes \`resolvedFrom\`/\`resolvedTo\` \u2014 use those coordinates for your next call.
|
|
112756
|
-
- **\`RANGE_GONE\`** \u2014 The text was deleted. Re-read the section with \`tandem_getTextContent\` and re-assess.
|
|
112757
|
-
- **\`INVALID_RANGE\`** \u2014 You hit heading markup (e.g., \`## \`). Target text content only, not the heading prefix.
|
|
112758
|
-
- **\`FORMAT_ERROR\`** \u2014 Attempted \`tandem_edit\` on a read-only \`.docx\`. Use annotations instead.
|
|
112759
|
-
|
|
112760
|
-
## Session Handoff
|
|
112761
|
-
|
|
112762
|
-
When starting a new Claude session with Tandem already running:
|
|
112763
|
-
|
|
112764
|
-
1. \`tandem_status()\` \u2014 check \`openDocuments\` array for restored sessions
|
|
112765
|
-
2. \`tandem_listDocuments()\` \u2014 see all open docs with details
|
|
112766
|
-
3. \`tandem_getOutline()\` \u2014 orient on the active document
|
|
112767
|
-
4. \`tandem_getAnnotations()\` \u2014 see what was already reviewed
|
|
112768
|
-
5. Continue where the previous session left off
|
|
112769
|
-
|
|
112770
|
-
## Multi-Document
|
|
112771
|
-
|
|
112772
|
-
When multiple documents are open, always pass \`documentId\` explicitly \u2014 omitting it targets the active document, which may have changed since your last call. Use \`tandem_listDocuments\` to see what's available. Cross-reference by reading both docs via \`tandem_getTextContent({ documentId: "..." })\` and annotating the relevant one.
|
|
112773
|
-
`;
|
|
112680
|
+
import { readFileSync } from "fs";
|
|
112681
|
+
import { dirname, resolve } from "path";
|
|
112682
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
112683
|
+
var __dirname = dirname(fileURLToPath2(import.meta.url));
|
|
112684
|
+
var SKILL_PATH = resolve(__dirname, "../../skills/tandem/SKILL.md");
|
|
112685
|
+
var SKILL_CONTENT = readFileSync(SKILL_PATH, "utf-8");
|
|
112774
112686
|
|
|
112775
112687
|
// src/cli/setup.ts
|
|
112776
|
-
var
|
|
112777
|
-
var
|
|
112688
|
+
var __dirname2 = dirname2(fileURLToPath3(import.meta.url));
|
|
112689
|
+
var PACKAGE_ROOT = resolve2(__dirname2, "../..");
|
|
112690
|
+
var CHANNEL_DIST = resolve2(PACKAGE_ROOT, "dist/channel/index.js");
|
|
112778
112691
|
var MCP_URL = `http://localhost:${DEFAULT_MCP_PORT}`;
|
|
112779
|
-
function buildMcpEntries(channelPath,
|
|
112780
|
-
|
|
112781
|
-
tandem: {
|
|
112782
|
-
|
|
112783
|
-
|
|
112784
|
-
|
|
112785
|
-
|
|
112786
|
-
command: nodeBinary,
|
|
112692
|
+
function buildMcpEntries(channelPath, opts = {}) {
|
|
112693
|
+
const entries = {
|
|
112694
|
+
tandem: { type: "http", url: `${MCP_URL}/mcp` }
|
|
112695
|
+
};
|
|
112696
|
+
if (opts.withChannelShim) {
|
|
112697
|
+
entries["tandem-channel"] = {
|
|
112698
|
+
command: opts.nodeBinary ?? "node",
|
|
112787
112699
|
args: [channelPath],
|
|
112788
112700
|
env: { TANDEM_URL: MCP_URL }
|
|
112789
|
-
}
|
|
112790
|
-
}
|
|
112701
|
+
};
|
|
112702
|
+
}
|
|
112703
|
+
return entries;
|
|
112791
112704
|
}
|
|
112792
112705
|
function detectTargets(opts = {}) {
|
|
112793
112706
|
const home = opts.homeOverride ?? homedir2();
|
|
@@ -112818,7 +112731,7 @@ function detectTargets(opts = {}) {
|
|
|
112818
112731
|
return targets;
|
|
112819
112732
|
}
|
|
112820
112733
|
async function atomicWrite3(content3, dest) {
|
|
112821
|
-
const tmp = join2(
|
|
112734
|
+
const tmp = join2(dirname2(dest), `.tandem-setup-${randomUUID4()}.tmp`);
|
|
112822
112735
|
await writeFile(tmp, content3, "utf-8");
|
|
112823
112736
|
try {
|
|
112824
112737
|
await rename(tmp, dest);
|
|
@@ -112839,14 +112752,23 @@ async function atomicWrite3(content3, dest) {
|
|
|
112839
112752
|
async function applyConfig(configPath, entries) {
|
|
112840
112753
|
let existing = {};
|
|
112841
112754
|
try {
|
|
112842
|
-
existing = JSON.parse(
|
|
112755
|
+
existing = JSON.parse(readFileSync2(configPath, "utf-8"));
|
|
112843
112756
|
} catch (err) {
|
|
112844
112757
|
const code3 = err.code;
|
|
112845
112758
|
if (code3 === "ENOENT") {
|
|
112846
112759
|
} else if (err instanceof SyntaxError) {
|
|
112847
|
-
|
|
112848
|
-
|
|
112849
|
-
|
|
112760
|
+
const backupPath = `${configPath}.broken-${Date.now()}`;
|
|
112761
|
+
try {
|
|
112762
|
+
await copyFile(configPath, backupPath);
|
|
112763
|
+
console.error(
|
|
112764
|
+
` Warning: ${configPath} contains malformed JSON \u2014 backed up to ${basename(backupPath)}, replacing with fresh config`
|
|
112765
|
+
);
|
|
112766
|
+
} catch (copyErr) {
|
|
112767
|
+
console.error(
|
|
112768
|
+
` Warning: ${configPath} contains malformed JSON and backup failed (${copyErr instanceof Error ? copyErr.message : copyErr}) \u2014 refusing to overwrite. Fix the JSON manually and rerun 'tandem setup'.`
|
|
112769
|
+
);
|
|
112770
|
+
throw copyErr;
|
|
112771
|
+
}
|
|
112850
112772
|
} else {
|
|
112851
112773
|
throw err;
|
|
112852
112774
|
}
|
|
@@ -112858,13 +112780,13 @@ async function applyConfig(configPath, entries) {
|
|
|
112858
112780
|
...entries
|
|
112859
112781
|
}
|
|
112860
112782
|
};
|
|
112861
|
-
await mkdir(
|
|
112783
|
+
await mkdir(dirname2(configPath), { recursive: true });
|
|
112862
112784
|
await atomicWrite3(JSON.stringify(updated, null, 2) + "\n", configPath);
|
|
112863
112785
|
}
|
|
112864
112786
|
async function installSkill(opts = {}) {
|
|
112865
112787
|
const home = opts.homeOverride ?? homedir2();
|
|
112866
112788
|
const skillPath = join2(home, ".claude", "skills", "tandem", "SKILL.md");
|
|
112867
|
-
await mkdir(
|
|
112789
|
+
await mkdir(dirname2(skillPath), { recursive: true });
|
|
112868
112790
|
await atomicWrite3(SKILL_CONTENT, skillPath);
|
|
112869
112791
|
}
|
|
112870
112792
|
|
|
@@ -113116,7 +113038,7 @@ async function runSetupHandler(input, homeOverride) {
|
|
|
113116
113038
|
};
|
|
113117
113039
|
}
|
|
113118
113040
|
const targets = detectTargets({ homeOverride });
|
|
113119
|
-
const entries = buildMcpEntries(channelPath, nodeBinary);
|
|
113041
|
+
const entries = buildMcpEntries(channelPath, { withChannelShim: true, nodeBinary });
|
|
113120
113042
|
const configured = [];
|
|
113121
113043
|
const errors = [];
|
|
113122
113044
|
for (const target of targets) {
|
|
@@ -113124,7 +113046,9 @@ async function runSetupHandler(input, homeOverride) {
|
|
|
113124
113046
|
await applyConfig(target.configPath, entries);
|
|
113125
113047
|
configured.push(target.label);
|
|
113126
113048
|
} catch (err) {
|
|
113127
|
-
|
|
113049
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
113050
|
+
errors.push(`${target.label}: ${msg}`);
|
|
113051
|
+
console.error(`[Setup] target=${target.label} failed: ${msg}`);
|
|
113128
113052
|
}
|
|
113129
113053
|
}
|
|
113130
113054
|
let skillInstalled = false;
|
|
@@ -113132,10 +113056,17 @@ async function runSetupHandler(input, homeOverride) {
|
|
|
113132
113056
|
await installSkill({ homeOverride });
|
|
113133
113057
|
skillInstalled = true;
|
|
113134
113058
|
} catch (err) {
|
|
113135
|
-
|
|
113136
|
-
|
|
113059
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
113060
|
+
errors.push(`Skill install: ${msg}`);
|
|
113061
|
+
console.error(`[Setup] skill install failed: ${msg}`);
|
|
113062
|
+
}
|
|
113063
|
+
const totalFailed = configured.length === 0 && !skillInstalled;
|
|
113064
|
+
const anyFailed = errors.length > 0;
|
|
113065
|
+
let status = 200;
|
|
113066
|
+
if (totalFailed) status = 500;
|
|
113067
|
+
else if (anyFailed) status = 207;
|
|
113137
113068
|
return {
|
|
113138
|
-
status
|
|
113069
|
+
status,
|
|
113139
113070
|
body: { data: { targets, configured, errors, skillInstalled } }
|
|
113140
113071
|
};
|
|
113141
113072
|
}
|
|
@@ -113969,8 +113900,8 @@ try {
|
|
|
113969
113900
|
`[Tandem] Could not read version from package.json: ${err instanceof Error ? err.message : err}`
|
|
113970
113901
|
);
|
|
113971
113902
|
}
|
|
113972
|
-
var
|
|
113973
|
-
var CLIENT_DIST = join3(
|
|
113903
|
+
var __dirname3 = dirname3(fileURLToPath4(import.meta.url));
|
|
113904
|
+
var CLIENT_DIST = join3(__dirname3, "../client");
|
|
113974
113905
|
var mcpServer = null;
|
|
113975
113906
|
var currentTransport = null;
|
|
113976
113907
|
var connectingPromise = null;
|
|
@@ -114108,7 +114039,7 @@ async function startMcpServerHttp(port, host = "127.0.0.1") {
|
|
|
114108
114039
|
} else {
|
|
114109
114040
|
console.error(`[Tandem] No client dist at ${CLIENT_DIST} \u2014 run 'npm run build' first`);
|
|
114110
114041
|
}
|
|
114111
|
-
return new Promise((
|
|
114042
|
+
return new Promise((resolve3, reject2) => {
|
|
114112
114043
|
const httpServer2 = app.listen(port, host, () => {
|
|
114113
114044
|
httpServer2.removeListener("error", reject2);
|
|
114114
114045
|
httpServer2.on("error", (err) => console.error("[Tandem] HTTP server error:", err));
|
|
@@ -114120,7 +114051,7 @@ async function startMcpServerHttp(port, host = "127.0.0.1") {
|
|
|
114120
114051
|
console.error("[Tandem] Skipping browser open \u2014 no client assets found");
|
|
114121
114052
|
}
|
|
114122
114053
|
}
|
|
114123
|
-
|
|
114054
|
+
resolve3(httpServer2);
|
|
114124
114055
|
});
|
|
114125
114056
|
httpServer2.on("error", reject2);
|
|
114126
114057
|
});
|
|
@@ -114338,7 +114269,7 @@ async function main2() {
|
|
|
114338
114269
|
} catch (err) {
|
|
114339
114270
|
console.error(`[Tandem] ${err instanceof Error ? err.message : err} \u2014 proceeding anyway`);
|
|
114340
114271
|
}
|
|
114341
|
-
const projectRoot = path12.resolve(path12.dirname(
|
|
114272
|
+
const projectRoot = path12.resolve(path12.dirname(fileURLToPath5(import.meta.url)), "../..");
|
|
114342
114273
|
try {
|
|
114343
114274
|
const versionStatus = await checkVersionChange(APP_VERSION, LAST_SEEN_VERSION_FILE);
|
|
114344
114275
|
if (versionStatus === "upgraded") {
|