@band-app/server 0.53.0 → 0.54.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/client/_shell.html +0 -0
- package/dist/client/assets/{TerminalPanel-CUrp7Wxk.js → TerminalPanel-CfzL015Z.js} +1 -1
- package/dist/client/assets/{_basePickBy-DzTpqc54.js → _basePickBy-DCBI2ZYZ.js} +1 -1
- package/dist/client/assets/{_baseUniq-BH8BhmRB.js → _baseUniq-DcG-qGfl.js} +1 -1
- package/dist/client/assets/{arc-C3KloRZC.js → arc-Dtd3NOeG.js} +1 -1
- package/dist/client/assets/{architectureDiagram-VXUJARFQ-C0v4c_1F.js → architectureDiagram-VXUJARFQ-_4wJCo66.js} +1 -1
- package/dist/client/assets/{blockDiagram-VD42YOAC-JA1asAF3.js → blockDiagram-VD42YOAC-BLg8A5DO.js} +1 -1
- package/dist/client/assets/{c4Diagram-YG6GDRKO-eDAKz1MH.js → c4Diagram-YG6GDRKO-1o6lovC1.js} +1 -1
- package/dist/client/assets/channel-CXnvJLnE.js +1 -0
- package/dist/client/assets/{chunk-4BX2VUAB-GiBdk6wd.js → chunk-4BX2VUAB-pUhlexDl.js} +1 -1
- package/dist/client/assets/{chunk-55IACEB6-CZirdcYj.js → chunk-55IACEB6-DIOOkGXI.js} +1 -1
- package/dist/client/assets/{chunk-B4BG7PRW-CRx24wmo.js → chunk-B4BG7PRW-betJcaMy.js} +1 -1
- package/dist/client/assets/{chunk-DI55MBZ5-BDlvmWyE.js → chunk-DI55MBZ5-Du6zLzqO.js} +1 -1
- package/dist/client/assets/{chunk-FMBD7UC4-CFQ4Ns-B.js → chunk-FMBD7UC4-jlnPGz3-.js} +1 -1
- package/dist/client/assets/{chunk-QN33PNHL-O1rjaqXm.js → chunk-QN33PNHL-BtZcZKWT.js} +1 -1
- package/dist/client/assets/{chunk-QZHKN3VN-BUex41N2.js → chunk-QZHKN3VN-CCXlh8PQ.js} +1 -1
- package/dist/client/assets/{chunk-TZMSLE5B-DJjv_do_.js → chunk-TZMSLE5B-EGqxu3bA.js} +1 -1
- package/dist/client/assets/classDiagram-2ON5EDUG-Dp5-cWrq.js +1 -0
- package/dist/client/assets/classDiagram-v2-WZHVMYZB-Dp5-cWrq.js +1 -0
- package/dist/client/assets/clone-D5FdW0HP.js +1 -0
- package/dist/client/assets/{cose-bilkent-S5V4N54A-DFpXjakt.js → cose-bilkent-S5V4N54A-CiQDuqKy.js} +1 -1
- package/dist/client/assets/{dagre-6UL2VRFP-CduI6jnM.js → dagre-6UL2VRFP-BV1RIA6i.js} +1 -1
- package/dist/client/assets/{diagram-PSM6KHXK-CzWJmLPu.js → diagram-PSM6KHXK-oZBpmBZ4.js} +1 -1
- package/dist/client/assets/{diagram-QEK2KX5R-CyCNI4-k.js → diagram-QEK2KX5R-BvBvt_5J.js} +1 -1
- package/dist/client/assets/{diagram-S2PKOQOG-C5wLA6ra.js → diagram-S2PKOQOG-sjeU7pbV.js} +1 -1
- package/dist/client/assets/{erDiagram-Q2GNP2WA-BNMyokGR.js → erDiagram-Q2GNP2WA-DnmU3JYj.js} +1 -1
- package/dist/client/assets/{flowDiagram-NV44I4VS-CDMiz1jN.js → flowDiagram-NV44I4VS-vWTy8wO1.js} +1 -1
- package/dist/client/assets/{ganttDiagram-JELNMOA3-BjKbhCuq.js → ganttDiagram-JELNMOA3-C8UgEfn6.js} +1 -1
- package/dist/client/assets/{gitGraphDiagram-V2S2FVAM-DcKCNdhS.js → gitGraphDiagram-V2S2FVAM-D4Y2-pQd.js} +1 -1
- package/dist/client/assets/{graph-BCkWMEPy.js → graph-wAJZ-snQ.js} +1 -1
- package/dist/client/assets/{highlighted-body-B3W2YXNL-ESHG-c2t.js → highlighted-body-B3W2YXNL-BS1x7lkZ.js} +1 -1
- package/dist/client/assets/{index-CJAA69-B.js → index-21p4gEDF.js} +1 -1
- package/dist/client/assets/{index-biU1uw37.js → index-B52rCane.js} +1 -1
- package/dist/client/assets/{index-kl_BbR04.js → index-BMcO1RPX.js} +1 -1
- package/dist/client/assets/{index-CklvaSBA.js → index-BULPK8ND.js} +1 -1
- package/dist/client/assets/{index-nnOiMGMS.js → index-CDRJgI3A.js} +1 -1
- package/dist/client/assets/{index-CutOvwS7.js → index-ClYtumza.js} +1 -1
- package/dist/client/assets/{index-Ong_o86j.js → index-CxNXgFPY.js} +1 -1
- package/dist/client/assets/{index-Bp2vWP2Y.js → index-DIelkckr.js} +1 -1
- package/dist/client/assets/{index-C4YFmo8L.js → index-DRo8uUPl.js} +1 -1
- package/dist/client/assets/{index-ChF20gAc.js → index-DvCvhnCb.js} +1 -1
- package/dist/client/assets/{index-MWMi8v82.js → index-Hh-Dy8VL.js} +1 -1
- package/dist/client/assets/{index-C3m3P5mw.js → index-ZYHE2FSs.js} +1 -1
- package/dist/client/assets/{index-D1w6ILcm.js → index-g0Sr5h74.js} +1 -1
- package/dist/client/assets/{infoDiagram-HS3SLOUP-CoptTTxB.js → infoDiagram-HS3SLOUP-CmZ04ZX2.js} +1 -1
- package/dist/client/assets/{journeyDiagram-XKPGCS4Q-CMN-HV9u.js → journeyDiagram-XKPGCS4Q-CyBTVa_6.js} +1 -1
- package/dist/client/assets/{kanban-definition-3W4ZIXB7-DC3laXMu.js → kanban-definition-3W4ZIXB7-C6sCohDW.js} +1 -1
- package/dist/client/assets/{layout-BNpvAk6E.js → layout-DbAdffkE.js} +1 -1
- package/dist/client/assets/main-BYKQWpTo.css +1 -0
- package/dist/client/assets/{main-Bgor0kVJ.js → main-DfjP5I-Q.js} +282 -282
- package/dist/client/assets/{mindmap-definition-VGOIOE7T-CFfDEH47.js → mindmap-definition-VGOIOE7T-D4byQ-t_.js} +1 -1
- package/dist/client/assets/{pieDiagram-ADFJNKIX-CZP5lrkz.js → pieDiagram-ADFJNKIX-SdHTH4tD.js} +1 -1
- package/dist/client/assets/{quadrantDiagram-AYHSOK5B-Bc1rWWnR.js → quadrantDiagram-AYHSOK5B-CctaxdVX.js} +1 -1
- package/dist/client/assets/{requirementDiagram-UZGBJVZJ-BtfVzz9o.js → requirementDiagram-UZGBJVZJ-BiuKR3TQ.js} +1 -1
- package/dist/client/assets/{sankeyDiagram-TZEHDZUN-CTFUjzzh.js → sankeyDiagram-TZEHDZUN-BTpPs36c.js} +1 -1
- package/dist/client/assets/{sequenceDiagram-WL72ISMW-Ceovvbrm.js → sequenceDiagram-WL72ISMW-BRAorH_1.js} +1 -1
- package/dist/client/assets/{stateDiagram-FKZM4ZOC-BboZL1pg.js → stateDiagram-FKZM4ZOC-BtHKF925.js} +1 -1
- package/dist/client/assets/stateDiagram-v2-4FDKWEC3-B40ZaZyn.js +1 -0
- package/dist/client/assets/{timeline-definition-IT6M3QCI-7vfajGp6.js → timeline-definition-IT6M3QCI-BxQS_MT5.js} +1 -1
- package/dist/client/assets/{treemap-GDKQZRPO-C1ZwadxG.js → treemap-GDKQZRPO-DdrDkT5H.js} +1 -1
- package/dist/client/assets/{worktree._worktreeId-C4_UcKsk.js → worktree._worktreeId-C2psBRXR.js} +1 -1
- package/dist/client/assets/{worktree._worktreeId-BmMetrj_.js → worktree._worktreeId-CVx6cyp5.js} +1 -1
- package/dist/client/assets/{xychartDiagram-PRI3JC2R-pTpN8cts.js → xychartDiagram-PRI3JC2R-R2Q9xRsW.js} +1 -1
- package/dist/start-server.mjs +410 -407
- package/package.json +9 -8
- package/dist/client/assets/channel-DO7Rw5s3.js +0 -1
- package/dist/client/assets/classDiagram-2ON5EDUG-Dydmjn5K.js +0 -1
- package/dist/client/assets/classDiagram-v2-WZHVMYZB-Dydmjn5K.js +0 -1
- package/dist/client/assets/clone-BBqOdmdW.js +0 -1
- package/dist/client/assets/main-oF1qBPU-.css +0 -1
- package/dist/client/assets/stateDiagram-v2-4FDKWEC3-BsPSpOyb.js +0 -1
package/dist/start-server.mjs
CHANGED
|
@@ -2136,7 +2136,7 @@ var require_thread_stream = __commonJS({
|
|
|
2136
2136
|
var { version: version3 } = require_package();
|
|
2137
2137
|
var { EventEmitter: EventEmitter4 } = __require("events");
|
|
2138
2138
|
var { Worker: Worker2 } = __require("worker_threads");
|
|
2139
|
-
var { join:
|
|
2139
|
+
var { join: join59 } = __require("path");
|
|
2140
2140
|
var { pathToFileURL } = __require("url");
|
|
2141
2141
|
var { wait } = require_wait();
|
|
2142
2142
|
var {
|
|
@@ -2172,7 +2172,7 @@ var require_thread_stream = __commonJS({
|
|
|
2172
2172
|
function createWorker(stream, opts) {
|
|
2173
2173
|
const { filename, workerData } = opts;
|
|
2174
2174
|
const bundlerOverrides = "__bundlerPathsOverrides" in globalThis ? globalThis.__bundlerPathsOverrides : {};
|
|
2175
|
-
const toExecute = bundlerOverrides["thread-stream-worker"] ||
|
|
2175
|
+
const toExecute = bundlerOverrides["thread-stream-worker"] || join59(__dirname, "lib", "worker.js");
|
|
2176
2176
|
const worker2 = new Worker2(toExecute, {
|
|
2177
2177
|
...opts.workerOpts,
|
|
2178
2178
|
trackUnmanagedFds: false,
|
|
@@ -2558,7 +2558,7 @@ var require_transport = __commonJS({
|
|
|
2558
2558
|
"use strict";
|
|
2559
2559
|
var { createRequire: createRequire2 } = __require("module");
|
|
2560
2560
|
var getCallers = require_caller();
|
|
2561
|
-
var { join:
|
|
2561
|
+
var { join: join59, isAbsolute: isAbsolute7, sep: sep11 } = __require("node:path");
|
|
2562
2562
|
var sleep3 = require_atomic_sleep();
|
|
2563
2563
|
var onExit = require_on_exit_leak_free();
|
|
2564
2564
|
var ThreadStream = require_thread_stream();
|
|
@@ -2621,7 +2621,7 @@ var require_transport = __commonJS({
|
|
|
2621
2621
|
throw new Error("only one of target or targets can be specified");
|
|
2622
2622
|
}
|
|
2623
2623
|
if (targets) {
|
|
2624
|
-
target = bundlerOverrides["pino-worker"] ||
|
|
2624
|
+
target = bundlerOverrides["pino-worker"] || join59(__dirname, "worker.js");
|
|
2625
2625
|
options.targets = targets.filter((dest) => dest.target).map((dest) => {
|
|
2626
2626
|
return {
|
|
2627
2627
|
...dest,
|
|
@@ -2639,7 +2639,7 @@ var require_transport = __commonJS({
|
|
|
2639
2639
|
});
|
|
2640
2640
|
});
|
|
2641
2641
|
} else if (pipeline3) {
|
|
2642
|
-
target = bundlerOverrides["pino-worker"] ||
|
|
2642
|
+
target = bundlerOverrides["pino-worker"] || join59(__dirname, "worker.js");
|
|
2643
2643
|
options.pipelines = [pipeline3.map((dest) => {
|
|
2644
2644
|
return {
|
|
2645
2645
|
...dest,
|
|
@@ -2661,7 +2661,7 @@ var require_transport = __commonJS({
|
|
|
2661
2661
|
return origin;
|
|
2662
2662
|
}
|
|
2663
2663
|
if (origin === "pino/file") {
|
|
2664
|
-
return
|
|
2664
|
+
return join59(__dirname, "..", "file.js");
|
|
2665
2665
|
}
|
|
2666
2666
|
let fixTarget2;
|
|
2667
2667
|
for (const filePath of callers) {
|
|
@@ -2989,11 +2989,11 @@ var require_tools = __commonJS({
|
|
|
2989
2989
|
}
|
|
2990
2990
|
}
|
|
2991
2991
|
}
|
|
2992
|
-
function buildFormatters(level, bindings,
|
|
2992
|
+
function buildFormatters(level, bindings, log90) {
|
|
2993
2993
|
return {
|
|
2994
2994
|
level,
|
|
2995
2995
|
bindings,
|
|
2996
|
-
log:
|
|
2996
|
+
log: log90
|
|
2997
2997
|
};
|
|
2998
2998
|
}
|
|
2999
2999
|
function normalizeDestFileDescriptor(destination) {
|
|
@@ -3376,11 +3376,11 @@ var require_proto = __commonJS({
|
|
|
3376
3376
|
}
|
|
3377
3377
|
} else instance[serializersSym] = serializers;
|
|
3378
3378
|
if (options.hasOwnProperty("formatters")) {
|
|
3379
|
-
const { level, bindings: chindings, log:
|
|
3379
|
+
const { level, bindings: chindings, log: log90 } = options.formatters;
|
|
3380
3380
|
instance[formattersSym] = buildFormatters(
|
|
3381
3381
|
level || formatters.level,
|
|
3382
3382
|
chindings || resetChildingsFormatter,
|
|
3383
|
-
|
|
3383
|
+
log90 || formatters.log
|
|
3384
3384
|
);
|
|
3385
3385
|
} else {
|
|
3386
3386
|
instance[formattersSym] = buildFormatters(
|
|
@@ -3650,7 +3650,7 @@ var require_safe_stable_stringify = __commonJS({
|
|
|
3650
3650
|
return circularValue;
|
|
3651
3651
|
}
|
|
3652
3652
|
let res = "";
|
|
3653
|
-
let
|
|
3653
|
+
let join59 = ",";
|
|
3654
3654
|
const originalIndentation = indentation;
|
|
3655
3655
|
if (Array.isArray(value)) {
|
|
3656
3656
|
if (value.length === 0) {
|
|
@@ -3664,7 +3664,7 @@ var require_safe_stable_stringify = __commonJS({
|
|
|
3664
3664
|
indentation += spacer;
|
|
3665
3665
|
res += `
|
|
3666
3666
|
${indentation}`;
|
|
3667
|
-
|
|
3667
|
+
join59 = `,
|
|
3668
3668
|
${indentation}`;
|
|
3669
3669
|
}
|
|
3670
3670
|
const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
|
|
@@ -3672,13 +3672,13 @@ ${indentation}`;
|
|
|
3672
3672
|
for (; i < maximumValuesToStringify - 1; i++) {
|
|
3673
3673
|
const tmp2 = stringifyFnReplacer(String(i), value, stack, replacer, spacer, indentation);
|
|
3674
3674
|
res += tmp2 !== void 0 ? tmp2 : "null";
|
|
3675
|
-
res +=
|
|
3675
|
+
res += join59;
|
|
3676
3676
|
}
|
|
3677
3677
|
const tmp = stringifyFnReplacer(String(i), value, stack, replacer, spacer, indentation);
|
|
3678
3678
|
res += tmp !== void 0 ? tmp : "null";
|
|
3679
3679
|
if (value.length - 1 > maximumBreadth) {
|
|
3680
3680
|
const removedKeys = value.length - maximumBreadth - 1;
|
|
3681
|
-
res += `${
|
|
3681
|
+
res += `${join59}"... ${getItemCount(removedKeys)} not stringified"`;
|
|
3682
3682
|
}
|
|
3683
3683
|
if (spacer !== "") {
|
|
3684
3684
|
res += `
|
|
@@ -3699,7 +3699,7 @@ ${originalIndentation}`;
|
|
|
3699
3699
|
let separator = "";
|
|
3700
3700
|
if (spacer !== "") {
|
|
3701
3701
|
indentation += spacer;
|
|
3702
|
-
|
|
3702
|
+
join59 = `,
|
|
3703
3703
|
${indentation}`;
|
|
3704
3704
|
whitespace = " ";
|
|
3705
3705
|
}
|
|
@@ -3713,13 +3713,13 @@ ${indentation}`;
|
|
|
3713
3713
|
const tmp = stringifyFnReplacer(key3, value, stack, replacer, spacer, indentation);
|
|
3714
3714
|
if (tmp !== void 0) {
|
|
3715
3715
|
res += `${separator}${strEscape(key3)}:${whitespace}${tmp}`;
|
|
3716
|
-
separator =
|
|
3716
|
+
separator = join59;
|
|
3717
3717
|
}
|
|
3718
3718
|
}
|
|
3719
3719
|
if (keyLength > maximumBreadth) {
|
|
3720
3720
|
const removedKeys = keyLength - maximumBreadth;
|
|
3721
3721
|
res += `${separator}"...":${whitespace}"${getItemCount(removedKeys)} not stringified"`;
|
|
3722
|
-
separator =
|
|
3722
|
+
separator = join59;
|
|
3723
3723
|
}
|
|
3724
3724
|
if (spacer !== "" && separator.length > 1) {
|
|
3725
3725
|
res = `
|
|
@@ -3760,7 +3760,7 @@ ${originalIndentation}`;
|
|
|
3760
3760
|
}
|
|
3761
3761
|
const originalIndentation = indentation;
|
|
3762
3762
|
let res = "";
|
|
3763
|
-
let
|
|
3763
|
+
let join59 = ",";
|
|
3764
3764
|
if (Array.isArray(value)) {
|
|
3765
3765
|
if (value.length === 0) {
|
|
3766
3766
|
return "[]";
|
|
@@ -3773,7 +3773,7 @@ ${originalIndentation}`;
|
|
|
3773
3773
|
indentation += spacer;
|
|
3774
3774
|
res += `
|
|
3775
3775
|
${indentation}`;
|
|
3776
|
-
|
|
3776
|
+
join59 = `,
|
|
3777
3777
|
${indentation}`;
|
|
3778
3778
|
}
|
|
3779
3779
|
const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
|
|
@@ -3781,13 +3781,13 @@ ${indentation}`;
|
|
|
3781
3781
|
for (; i < maximumValuesToStringify - 1; i++) {
|
|
3782
3782
|
const tmp2 = stringifyArrayReplacer(String(i), value[i], stack, replacer, spacer, indentation);
|
|
3783
3783
|
res += tmp2 !== void 0 ? tmp2 : "null";
|
|
3784
|
-
res +=
|
|
3784
|
+
res += join59;
|
|
3785
3785
|
}
|
|
3786
3786
|
const tmp = stringifyArrayReplacer(String(i), value[i], stack, replacer, spacer, indentation);
|
|
3787
3787
|
res += tmp !== void 0 ? tmp : "null";
|
|
3788
3788
|
if (value.length - 1 > maximumBreadth) {
|
|
3789
3789
|
const removedKeys = value.length - maximumBreadth - 1;
|
|
3790
|
-
res += `${
|
|
3790
|
+
res += `${join59}"... ${getItemCount(removedKeys)} not stringified"`;
|
|
3791
3791
|
}
|
|
3792
3792
|
if (spacer !== "") {
|
|
3793
3793
|
res += `
|
|
@@ -3800,7 +3800,7 @@ ${originalIndentation}`;
|
|
|
3800
3800
|
let whitespace = "";
|
|
3801
3801
|
if (spacer !== "") {
|
|
3802
3802
|
indentation += spacer;
|
|
3803
|
-
|
|
3803
|
+
join59 = `,
|
|
3804
3804
|
${indentation}`;
|
|
3805
3805
|
whitespace = " ";
|
|
3806
3806
|
}
|
|
@@ -3809,7 +3809,7 @@ ${indentation}`;
|
|
|
3809
3809
|
const tmp = stringifyArrayReplacer(key3, value[key3], stack, replacer, spacer, indentation);
|
|
3810
3810
|
if (tmp !== void 0) {
|
|
3811
3811
|
res += `${separator}${strEscape(key3)}:${whitespace}${tmp}`;
|
|
3812
|
-
separator =
|
|
3812
|
+
separator = join59;
|
|
3813
3813
|
}
|
|
3814
3814
|
}
|
|
3815
3815
|
if (spacer !== "" && separator.length > 1) {
|
|
@@ -3867,20 +3867,20 @@ ${originalIndentation}`;
|
|
|
3867
3867
|
indentation += spacer;
|
|
3868
3868
|
let res2 = `
|
|
3869
3869
|
${indentation}`;
|
|
3870
|
-
const
|
|
3870
|
+
const join60 = `,
|
|
3871
3871
|
${indentation}`;
|
|
3872
3872
|
const maximumValuesToStringify = Math.min(value.length, maximumBreadth);
|
|
3873
3873
|
let i = 0;
|
|
3874
3874
|
for (; i < maximumValuesToStringify - 1; i++) {
|
|
3875
3875
|
const tmp2 = stringifyIndent(String(i), value[i], stack, spacer, indentation);
|
|
3876
3876
|
res2 += tmp2 !== void 0 ? tmp2 : "null";
|
|
3877
|
-
res2 +=
|
|
3877
|
+
res2 += join60;
|
|
3878
3878
|
}
|
|
3879
3879
|
const tmp = stringifyIndent(String(i), value[i], stack, spacer, indentation);
|
|
3880
3880
|
res2 += tmp !== void 0 ? tmp : "null";
|
|
3881
3881
|
if (value.length - 1 > maximumBreadth) {
|
|
3882
3882
|
const removedKeys = value.length - maximumBreadth - 1;
|
|
3883
|
-
res2 += `${
|
|
3883
|
+
res2 += `${join60}"... ${getItemCount(removedKeys)} not stringified"`;
|
|
3884
3884
|
}
|
|
3885
3885
|
res2 += `
|
|
3886
3886
|
${originalIndentation}`;
|
|
@@ -3896,16 +3896,16 @@ ${originalIndentation}`;
|
|
|
3896
3896
|
return '"[Object]"';
|
|
3897
3897
|
}
|
|
3898
3898
|
indentation += spacer;
|
|
3899
|
-
const
|
|
3899
|
+
const join59 = `,
|
|
3900
3900
|
${indentation}`;
|
|
3901
3901
|
let res = "";
|
|
3902
3902
|
let separator = "";
|
|
3903
3903
|
let maximumPropertiesToStringify = Math.min(keyLength, maximumBreadth);
|
|
3904
3904
|
if (isTypedArrayWithEntries(value)) {
|
|
3905
|
-
res += stringifyTypedArray(value,
|
|
3905
|
+
res += stringifyTypedArray(value, join59, maximumBreadth);
|
|
3906
3906
|
keys = keys.slice(value.length);
|
|
3907
3907
|
maximumPropertiesToStringify -= value.length;
|
|
3908
|
-
separator =
|
|
3908
|
+
separator = join59;
|
|
3909
3909
|
}
|
|
3910
3910
|
if (deterministic) {
|
|
3911
3911
|
keys = sort(keys, comparator2);
|
|
@@ -3916,13 +3916,13 @@ ${indentation}`;
|
|
|
3916
3916
|
const tmp = stringifyIndent(key3, value[key3], stack, spacer, indentation);
|
|
3917
3917
|
if (tmp !== void 0) {
|
|
3918
3918
|
res += `${separator}${strEscape(key3)}: ${tmp}`;
|
|
3919
|
-
separator =
|
|
3919
|
+
separator = join59;
|
|
3920
3920
|
}
|
|
3921
3921
|
}
|
|
3922
3922
|
if (keyLength > maximumBreadth) {
|
|
3923
3923
|
const removedKeys = keyLength - maximumBreadth;
|
|
3924
3924
|
res += `${separator}"...": "${getItemCount(removedKeys)} not stringified"`;
|
|
3925
|
-
separator =
|
|
3925
|
+
separator = join59;
|
|
3926
3926
|
}
|
|
3927
3927
|
if (separator !== "") {
|
|
3928
3928
|
res = `
|
|
@@ -14699,7 +14699,7 @@ var require_websocket = __commonJS({
|
|
|
14699
14699
|
var http = __require("http");
|
|
14700
14700
|
var net = __require("net");
|
|
14701
14701
|
var tls = __require("tls");
|
|
14702
|
-
var { randomBytes: randomBytes17, createHash:
|
|
14702
|
+
var { randomBytes: randomBytes17, createHash: createHash14 } = __require("crypto");
|
|
14703
14703
|
var { Duplex, Readable: Readable3 } = __require("stream");
|
|
14704
14704
|
var { URL: URL2 } = __require("url");
|
|
14705
14705
|
var PerMessageDeflate = require_permessage_deflate();
|
|
@@ -15359,7 +15359,7 @@ var require_websocket = __commonJS({
|
|
|
15359
15359
|
abortHandshake(websocket, socket, "Invalid Upgrade header");
|
|
15360
15360
|
return;
|
|
15361
15361
|
}
|
|
15362
|
-
const digest2 =
|
|
15362
|
+
const digest2 = createHash14("sha1").update(key2 + GUID).digest("base64");
|
|
15363
15363
|
if (res.headers["sec-websocket-accept"] !== digest2) {
|
|
15364
15364
|
abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
|
|
15365
15365
|
return;
|
|
@@ -15726,7 +15726,7 @@ var require_websocket_server = __commonJS({
|
|
|
15726
15726
|
var EventEmitter4 = __require("events");
|
|
15727
15727
|
var http = __require("http");
|
|
15728
15728
|
var { Duplex } = __require("stream");
|
|
15729
|
-
var { createHash:
|
|
15729
|
+
var { createHash: createHash14 } = __require("crypto");
|
|
15730
15730
|
var extension = require_extension();
|
|
15731
15731
|
var PerMessageDeflate = require_permessage_deflate();
|
|
15732
15732
|
var subprotocol = require_subprotocol();
|
|
@@ -16027,7 +16027,7 @@ var require_websocket_server = __commonJS({
|
|
|
16027
16027
|
);
|
|
16028
16028
|
}
|
|
16029
16029
|
if (this._state > RUNNING) return abortHandshake(socket, 503);
|
|
16030
|
-
const digest2 =
|
|
16030
|
+
const digest2 = createHash14("sha1").update(key2 + GUID).digest("base64");
|
|
16031
16031
|
const headers = [
|
|
16032
16032
|
"HTTP/1.1 101 Switching Protocols",
|
|
16033
16033
|
"Upgrade: websocket",
|
|
@@ -41799,7 +41799,7 @@ var init_sql = __esm({
|
|
|
41799
41799
|
return new SQL([new StringChunk(str4)]);
|
|
41800
41800
|
}
|
|
41801
41801
|
_sql.raw = raw;
|
|
41802
|
-
function
|
|
41802
|
+
function join59(chunks, separator) {
|
|
41803
41803
|
const result = [];
|
|
41804
41804
|
for (const [i, chunk] of chunks.entries()) {
|
|
41805
41805
|
if (i > 0 && separator !== void 0) result.push(separator);
|
|
@@ -41807,7 +41807,7 @@ var init_sql = __esm({
|
|
|
41807
41807
|
}
|
|
41808
41808
|
return new SQL(result);
|
|
41809
41809
|
}
|
|
41810
|
-
_sql.join =
|
|
41810
|
+
_sql.join = join59;
|
|
41811
41811
|
function identifier(value) {
|
|
41812
41812
|
return new Name(value);
|
|
41813
41813
|
}
|
|
@@ -43735,7 +43735,7 @@ var init_sql2 = __esm({
|
|
|
43735
43735
|
return new SQL3([new StringChunk2(str4)]);
|
|
43736
43736
|
}
|
|
43737
43737
|
_sql.raw = raw;
|
|
43738
|
-
function
|
|
43738
|
+
function join59(chunks, separator) {
|
|
43739
43739
|
const result = [];
|
|
43740
43740
|
for (const [i, chunk] of chunks.entries()) {
|
|
43741
43741
|
if (i > 0 && separator !== void 0) result.push(separator);
|
|
@@ -43743,7 +43743,7 @@ var init_sql2 = __esm({
|
|
|
43743
43743
|
}
|
|
43744
43744
|
return new SQL3(result);
|
|
43745
43745
|
}
|
|
43746
|
-
_sql.join =
|
|
43746
|
+
_sql.join = join59;
|
|
43747
43747
|
function identifier(value) {
|
|
43748
43748
|
return new Name2(value);
|
|
43749
43749
|
}
|
|
@@ -48936,7 +48936,7 @@ var init_select3 = __esm({
|
|
|
48936
48936
|
const baseTableName = this.tableName;
|
|
48937
48937
|
const tableName = getTableLikeName(table);
|
|
48938
48938
|
for (const item of extractUsedTable(table)) this.usedTables.add(item);
|
|
48939
|
-
if (typeof tableName === "string" && this.config.joins?.some((
|
|
48939
|
+
if (typeof tableName === "string" && this.config.joins?.some((join59) => join59.alias === tableName)) throw new Error(`Alias "${tableName}" is already used in this query`);
|
|
48940
48940
|
if (!this.isPartialSelect) {
|
|
48941
48941
|
if (Object.keys(this.joinsNotNullableMap).length === 1 && typeof baseTableName === "string") this.config.fields = { [baseTableName]: this.config.fields };
|
|
48942
48942
|
if (typeof tableName === "string" && !is2(table, SQL3)) {
|
|
@@ -50201,7 +50201,7 @@ var init_dialect = __esm({
|
|
|
50201
50201
|
if (!joins2) return;
|
|
50202
50202
|
const withEntries = Object.entries(joins2).filter(([_2, v2]) => v2);
|
|
50203
50203
|
if (!withEntries.length) return;
|
|
50204
|
-
return sql2.join(withEntries.map(([k2,
|
|
50204
|
+
return sql2.join(withEntries.map(([k2, join59]) => {
|
|
50205
50205
|
const relation = tableConfig.relations[k2];
|
|
50206
50206
|
const isSingle2 = is2(relation, One);
|
|
50207
50207
|
const targetTable = aliasedTable(relation.targetTable, `d${currentDepth + 1}`);
|
|
@@ -50212,7 +50212,7 @@ var init_dialect = __esm({
|
|
|
50212
50212
|
table: targetTable,
|
|
50213
50213
|
mode: isSingle2 ? "first" : "many",
|
|
50214
50214
|
schema,
|
|
50215
|
-
queryConfig:
|
|
50215
|
+
queryConfig: join59,
|
|
50216
50216
|
tableConfig: schema[relation.targetTableName],
|
|
50217
50217
|
relationWhere: filter,
|
|
50218
50218
|
isNested: true,
|
|
@@ -50226,7 +50226,7 @@ var init_dialect = __esm({
|
|
|
50226
50226
|
key: k2,
|
|
50227
50227
|
selection: innerQuery.selection,
|
|
50228
50228
|
isArray: !isSingle2,
|
|
50229
|
-
isOptional: (relation.optional ?? false) ||
|
|
50229
|
+
isOptional: (relation.optional ?? false) || join59 !== true && !!join59.where
|
|
50230
50230
|
});
|
|
50231
50231
|
const jsonColumns = sql2.join(innerQuery.selection.map((s2) => {
|
|
50232
50232
|
return sql2`${sql2.raw(this.escapeString(s2.key))}, ${s2.selection ? sql2`${jsonb2}(${sql2.identifier(s2.key)})` : sql2.identifier(s2.key)}`;
|
|
@@ -50745,7 +50745,7 @@ var init_update = __esm({
|
|
|
50745
50745
|
createJoin(joinType) {
|
|
50746
50746
|
return ((table, on) => {
|
|
50747
50747
|
const tableName = getTableLikeName(table);
|
|
50748
|
-
if (typeof tableName === "string" && this.config.joins.some((
|
|
50748
|
+
if (typeof tableName === "string" && this.config.joins.some((join59) => join59.alias === tableName)) throw new Error(`Alias "${tableName}" is already used in this query`);
|
|
50749
50749
|
if (typeof on === "function") {
|
|
50750
50750
|
const from = this.config.from ? is2(table, SQLiteTable2) ? table[Table2.Symbol.Columns] : is2(table, Subquery2) ? table._.selectedFields : is2(table, SQLiteViewBase) ? table[ViewBaseConfig2].selectedFields : void 0 : void 0;
|
|
50751
50751
|
on = on(new Proxy(this.config.table[Table2.Symbol.Columns], new SelectionProxyHandler({
|
|
@@ -54081,7 +54081,7 @@ import { lstatSync as lstatSync3, realpathSync as realpathSync4 } from "node:fs"
|
|
|
54081
54081
|
import { platform } from "node:os";
|
|
54082
54082
|
import { delimiter as delimiter3, join as join19, resolve as resolve4 } from "node:path";
|
|
54083
54083
|
function findCliBinaryAt(opts) {
|
|
54084
|
-
const { cwd, dirname:
|
|
54084
|
+
const { cwd, dirname: dirname18 } = opts;
|
|
54085
54085
|
const exe = platform() === "win32" ? "band.exe" : "band";
|
|
54086
54086
|
const explicit = process.env.BAND_CLI_PATH;
|
|
54087
54087
|
if (explicit) {
|
|
@@ -54097,7 +54097,7 @@ function findCliBinaryAt(opts) {
|
|
|
54097
54097
|
// cwd = repo root (fallback)
|
|
54098
54098
|
resolve4(cwd, "apps"),
|
|
54099
54099
|
// From this source file in dev (packages/host-local/src/process/ → apps/)
|
|
54100
|
-
resolve4(
|
|
54100
|
+
resolve4(dirname18, "..", "..", "..", "..", "apps"),
|
|
54101
54101
|
// From bundled `dist/` file (<Resources>/web/dist/ → <Resources>/) only
|
|
54102
54102
|
// — in dev mode this resolves to `packages/`, which has no
|
|
54103
54103
|
// `cli/target/<profile>/band` and is harmless; the walk above is the
|
|
@@ -54105,7 +54105,7 @@ function findCliBinaryAt(opts) {
|
|
|
54105
54105
|
// layout under <Resources>/cli/ would still resolve. Today's Electron
|
|
54106
54106
|
// bundle ships the binary under `binaries/` (handled by Strategy B),
|
|
54107
54107
|
// so this strategy never hits in production either.
|
|
54108
|
-
resolve4(
|
|
54108
|
+
resolve4(dirname18, "..", "..", "..")
|
|
54109
54109
|
];
|
|
54110
54110
|
for (const appsDir of appsStrategies) {
|
|
54111
54111
|
for (const profile of ["release", "debug"]) {
|
|
@@ -54122,7 +54122,7 @@ function findCliBinaryAt(opts) {
|
|
|
54122
54122
|
resolve4(cwd, "..", "binaries", exe),
|
|
54123
54123
|
// From the bundled dist file (<Resources>/web/dist/start-server.mjs)
|
|
54124
54124
|
// → <Resources>/binaries/band
|
|
54125
|
-
resolve4(
|
|
54125
|
+
resolve4(dirname18, "..", "..", "binaries", exe)
|
|
54126
54126
|
];
|
|
54127
54127
|
for (const p2 of electronCandidates) {
|
|
54128
54128
|
try {
|
|
@@ -63153,10 +63153,10 @@ var init_agent_command = __esm({
|
|
|
63153
63153
|
import { readdirSync as readdirSync8 } from "node:fs";
|
|
63154
63154
|
import { mkdir as mkdir5 } from "node:fs/promises";
|
|
63155
63155
|
import { join as join38 } from "node:path";
|
|
63156
|
-
async function openSharedDir(worktreeId4) {
|
|
63156
|
+
async function openSharedDir(worktreeId4, chatId) {
|
|
63157
63157
|
const host = hostRegistry.hostFor(worktreeId4);
|
|
63158
63158
|
if (host.id === hostRegistry.local.id) {
|
|
63159
|
-
const path3 = join38(bandHome(), "shared", worktreeId4);
|
|
63159
|
+
const path3 = join38(bandHome(), "shared", worktreeId4, chatId);
|
|
63160
63160
|
await mkdir5(path3, { recursive: true });
|
|
63161
63161
|
return {
|
|
63162
63162
|
path: path3,
|
|
@@ -63171,7 +63171,7 @@ async function openSharedDir(worktreeId4) {
|
|
|
63171
63171
|
}
|
|
63172
63172
|
const dirs = (await host.info()).dirs;
|
|
63173
63173
|
if (!dirs) throw new Error(`Worker ${host.id} has no directory for shared files`);
|
|
63174
|
-
const path2 = join38(dirs.shared, worktreeId4);
|
|
63174
|
+
const path2 = join38(dirs.shared, worktreeId4, chatId);
|
|
63175
63175
|
await host.fs.mkdir(path2, { recursive: true });
|
|
63176
63176
|
return {
|
|
63177
63177
|
path: path2,
|
|
@@ -63192,6 +63192,25 @@ async function agentExtraDirs(worktreeId4) {
|
|
|
63192
63192
|
const dirs = (await host.info()).dirs;
|
|
63193
63193
|
return dirs ? [dirs.uploads, dirs.shared] : [];
|
|
63194
63194
|
}
|
|
63195
|
+
function sharedFileUrl(worktreeId4, chatId, filename) {
|
|
63196
|
+
return `/api/shared/${encodeURIComponent(worktreeId4)}/${encodeURIComponent(chatId)}/${encodeURIComponent(filename)}`;
|
|
63197
|
+
}
|
|
63198
|
+
function parseSharedPath(rest) {
|
|
63199
|
+
const raw = rest.split("?")[0].split("/");
|
|
63200
|
+
if (raw.length !== 2 && raw.length !== 3) return null;
|
|
63201
|
+
const parts = [];
|
|
63202
|
+
for (const segment of raw) {
|
|
63203
|
+
let decoded;
|
|
63204
|
+
try {
|
|
63205
|
+
decoded = decodeURIComponent(segment);
|
|
63206
|
+
} catch {
|
|
63207
|
+
return null;
|
|
63208
|
+
}
|
|
63209
|
+
if (!decoded || decoded === "." || decoded === ".." || /[/\\\0]/.test(decoded)) return null;
|
|
63210
|
+
parts.push(decoded);
|
|
63211
|
+
}
|
|
63212
|
+
return parts.length === 3 ? { worktreeId: parts[0], chatId: parts[1], name: parts[2] } : { worktreeId: parts[0], name: parts[1] };
|
|
63213
|
+
}
|
|
63195
63214
|
var init_shared_dir = __esm({
|
|
63196
63215
|
"src/server/services/_utils/shared-dir.ts"() {
|
|
63197
63216
|
"use strict";
|
|
@@ -68229,7 +68248,7 @@ function turnUsage(res, ctx) {
|
|
|
68229
68248
|
return { ...usage, model, costUsd: (previousCost ?? 0) + cost };
|
|
68230
68249
|
}
|
|
68231
68250
|
function sharedDirNote(sharedDir) {
|
|
68232
|
-
return `[File sharing: to send a file to the user, write or copy it to ${sharedDir}/ and it will appear as a
|
|
68251
|
+
return `[File sharing: to send a file to the user, write or copy it to ${sharedDir}/ and it will appear as a file card in this chat.]`;
|
|
68233
68252
|
}
|
|
68234
68253
|
function fileUri(path2) {
|
|
68235
68254
|
return `file://${path2.split("/").map(encodeURIComponent).join("/")}`;
|
|
@@ -68729,6 +68748,8 @@ var init_session3 = __esm({
|
|
|
68729
68748
|
this.misses = opts.heartbeatMisses ?? HEARTBEAT_MISSES;
|
|
68730
68749
|
this.nextChan = opts.role === "client" ? 1 : 2;
|
|
68731
68750
|
}
|
|
68751
|
+
/** Close code and reason of the last socket that ended. Code 1006 means no close frame arrived. */
|
|
68752
|
+
lastClose = null;
|
|
68732
68753
|
get attached() {
|
|
68733
68754
|
return this.ws !== null && this.ws.readyState === 1;
|
|
68734
68755
|
}
|
|
@@ -68823,8 +68844,10 @@ var init_session3 = __esm({
|
|
|
68823
68844
|
ws.on("message", (data, isBinary) => {
|
|
68824
68845
|
if (this.ws === ws) this.onMessage(data, isBinary);
|
|
68825
68846
|
});
|
|
68826
|
-
ws.on("close", () => {
|
|
68827
|
-
if (this.ws
|
|
68847
|
+
ws.on("close", (code, reason) => {
|
|
68848
|
+
if (this.ws !== ws) return;
|
|
68849
|
+
this.lastClose = { code, reason: reason.toString().slice(0, 200) };
|
|
68850
|
+
this.detach();
|
|
68828
68851
|
});
|
|
68829
68852
|
ws.on("error", () => {
|
|
68830
68853
|
});
|
|
@@ -68913,34 +68936,40 @@ var init_session3 = __esm({
|
|
|
68913
68936
|
let frame;
|
|
68914
68937
|
try {
|
|
68915
68938
|
frame = decodeFrame(Buffer.isBuffer(data) ? data : Buffer.from(data));
|
|
68916
|
-
} catch {
|
|
68917
|
-
this.
|
|
68939
|
+
} catch (err) {
|
|
68940
|
+
this.cut("undecodable frame", err);
|
|
68918
68941
|
return;
|
|
68919
68942
|
}
|
|
68920
68943
|
try {
|
|
68921
68944
|
this.channels.get(frame.chan)?.handleFrame(frame);
|
|
68922
|
-
} catch {
|
|
68923
|
-
this.
|
|
68945
|
+
} catch (err) {
|
|
68946
|
+
this.cut(`channel ${frame.chan} failed to handle a frame`, err);
|
|
68924
68947
|
}
|
|
68925
68948
|
return;
|
|
68926
68949
|
}
|
|
68927
68950
|
let msg;
|
|
68928
68951
|
try {
|
|
68929
68952
|
msg = JSON.parse(data.toString());
|
|
68930
|
-
} catch {
|
|
68931
|
-
this.
|
|
68953
|
+
} catch (err) {
|
|
68954
|
+
this.cut("unparsable message", err);
|
|
68932
68955
|
return;
|
|
68933
68956
|
}
|
|
68934
68957
|
if (msg === null || typeof msg !== "object") {
|
|
68935
|
-
this.
|
|
68958
|
+
this.cut("message is not an object");
|
|
68936
68959
|
return;
|
|
68937
68960
|
}
|
|
68938
68961
|
try {
|
|
68939
68962
|
this.dispatchText(msg);
|
|
68940
|
-
} catch {
|
|
68941
|
-
this.
|
|
68963
|
+
} catch (err) {
|
|
68964
|
+
this.cut("invalid message", err);
|
|
68942
68965
|
}
|
|
68943
68966
|
}
|
|
68967
|
+
/** Drops the socket after a protocol violation, and says why, so the drop is not silent. */
|
|
68968
|
+
cut(reason, err) {
|
|
68969
|
+
const detail = err instanceof Error ? `: ${err.message}` : "";
|
|
68970
|
+
this.emit("fault", `${reason}${detail}`);
|
|
68971
|
+
this.ws?.terminate();
|
|
68972
|
+
}
|
|
68944
68973
|
dispatchText(msg) {
|
|
68945
68974
|
if (typeof msg.method === "string") {
|
|
68946
68975
|
if ("id" in msg && msg.id !== void 0 && msg.id !== null)
|
|
@@ -68965,14 +68994,32 @@ var init_session3 = __esm({
|
|
|
68965
68994
|
throw new Error("malformed link.open");
|
|
68966
68995
|
}
|
|
68967
68996
|
if (this.channels.has(p2.chan) || this.tombstones.has(p2.chan)) return;
|
|
68968
|
-
if (this.channels.size >= MAX_CHANNELS)
|
|
68997
|
+
if (this.channels.size >= MAX_CHANNELS) {
|
|
68998
|
+
this.emit("fault", `refused channel ${p2.chan}: too many channels`);
|
|
68999
|
+
this.writeBinary(
|
|
69000
|
+
encodeFrame({
|
|
69001
|
+
chan: p2.chan,
|
|
69002
|
+
seq: 0,
|
|
69003
|
+
kind: "reset",
|
|
69004
|
+
payload: Buffer.from("too many channels")
|
|
69005
|
+
})
|
|
69006
|
+
);
|
|
69007
|
+
return;
|
|
69008
|
+
}
|
|
68969
69009
|
const ch = new Channel(this, p2.chan, p2.name, p2.meta, this.window);
|
|
68970
69010
|
this.channels.set(p2.chan, ch);
|
|
68971
69011
|
this.emit("channel", ch);
|
|
68972
69012
|
return;
|
|
68973
69013
|
}
|
|
68974
69014
|
}
|
|
68975
|
-
|
|
69015
|
+
try {
|
|
69016
|
+
this.notifyHandlers.get(msg.method)?.(msg.params);
|
|
69017
|
+
} catch (err) {
|
|
69018
|
+
this.emit(
|
|
69019
|
+
"fault",
|
|
69020
|
+
`notification ${msg.method} handler threw: ${err instanceof Error ? err.message : String(err)}`
|
|
69021
|
+
);
|
|
69022
|
+
}
|
|
68976
69023
|
}
|
|
68977
69024
|
async onRequest(msg) {
|
|
68978
69025
|
const handler = this.handlers.get(msg.method);
|
|
@@ -69110,7 +69157,7 @@ var init_payload = __esm({
|
|
|
69110
69157
|
});
|
|
69111
69158
|
|
|
69112
69159
|
// ../../packages/link/src/relay.ts
|
|
69113
|
-
var METHOD_RELAY_REGISTER, METHOD_RELAY_REVOKE, METHOD_RELAY_HTTP, RELAY_MAX_BODY_BYTES,
|
|
69160
|
+
var METHOD_RELAY_REGISTER, METHOD_RELAY_REVOKE, METHOD_RELAY_HTTP, RELAY_MAX_BODY_BYTES, METHOD_LIFECYCLE_IDLE, METHOD_LIFECYCLE_POLICY, METHOD_LIFECYCLE_SLEEP, METHOD_LIFECYCLE_SHUTDOWN, METHOD_LIFECYCLE_EXPORT_SESSIONS, METHOD_LIFECYCLE_IMPORT_SESSIONS, METHOD_GIT_CREDENTIAL, METHOD_GH_TOKEN, METHOD_LEASE_RENEW, METHOD_WORKER_UPDATE;
|
|
69114
69161
|
var init_relay = __esm({
|
|
69115
69162
|
"../../packages/link/src/relay.ts"() {
|
|
69116
69163
|
"use strict";
|
|
@@ -69118,7 +69165,6 @@ var init_relay = __esm({
|
|
|
69118
69165
|
METHOD_RELAY_REVOKE = "relay.revoke";
|
|
69119
69166
|
METHOD_RELAY_HTTP = "relay.http";
|
|
69120
69167
|
RELAY_MAX_BODY_BYTES = 512 * 1024;
|
|
69121
|
-
METHOD_CLI_FETCH = "cli.fetch";
|
|
69122
69168
|
METHOD_LIFECYCLE_IDLE = "lifecycle.idle";
|
|
69123
69169
|
METHOD_LIFECYCLE_POLICY = "lifecycle.policy";
|
|
69124
69170
|
METHOD_LIFECYCLE_SLEEP = "lifecycle.sleep";
|
|
@@ -69324,7 +69370,8 @@ var init_server3 = __esm({
|
|
|
69324
69370
|
resumed,
|
|
69325
69371
|
wsPing: true
|
|
69326
69372
|
});
|
|
69327
|
-
} catch {
|
|
69373
|
+
} catch (err) {
|
|
69374
|
+
this.emit("fault", session, `attach failed: ${err instanceof Error ? err.message : err}`);
|
|
69328
69375
|
ws.terminate();
|
|
69329
69376
|
return;
|
|
69330
69377
|
}
|
|
@@ -69341,6 +69388,7 @@ var init_server3 = __esm({
|
|
|
69341
69388
|
this.expiry.set(session.workerId, t2);
|
|
69342
69389
|
});
|
|
69343
69390
|
session.on("lost", () => this.emit("lost", session));
|
|
69391
|
+
session.on("fault", (reason) => this.emit("fault", session, reason));
|
|
69344
69392
|
}
|
|
69345
69393
|
dropSession(session, reason) {
|
|
69346
69394
|
clearTimeout(this.expiry.get(session.workerId));
|
|
@@ -70413,7 +70461,7 @@ async function runTask(task) {
|
|
|
70413
70461
|
}
|
|
70414
70462
|
if (task.model) await applyTurnChoice(chatId, "model", task.model);
|
|
70415
70463
|
if (task.mode) await applyTurnChoice(chatId, "mode", task.mode);
|
|
70416
|
-
const shared2 = await openSharedDir(task.worktreeId);
|
|
70464
|
+
const shared2 = await openSharedDir(task.worktreeId, chatId);
|
|
70417
70465
|
const seenShared = new Set(await shared2.list());
|
|
70418
70466
|
const announce = (names) => {
|
|
70419
70467
|
for (const filename of names) {
|
|
@@ -70422,7 +70470,7 @@ async function runTask(task) {
|
|
|
70422
70470
|
agentSessionService.record(chatId, {
|
|
70423
70471
|
type: "file",
|
|
70424
70472
|
mediaType: mimeTypeFromFilename(filename),
|
|
70425
|
-
url:
|
|
70473
|
+
url: sharedFileUrl(task.worktreeId, chatId, filename),
|
|
70426
70474
|
filename
|
|
70427
70475
|
});
|
|
70428
70476
|
}
|
|
@@ -72197,8 +72245,8 @@ var init_environment_builds = __esm({
|
|
|
72197
72245
|
get(id) {
|
|
72198
72246
|
return getDb().select().from(environmentBuilds).where(eq2(environmentBuilds.id, id)).get();
|
|
72199
72247
|
}
|
|
72200
|
-
setLog(id,
|
|
72201
|
-
getDb().update(environmentBuilds).set({ log:
|
|
72248
|
+
setLog(id, log90) {
|
|
72249
|
+
getDb().update(environmentBuilds).set({ log: log90 }).where(eq2(environmentBuilds.id, id)).run();
|
|
72202
72250
|
}
|
|
72203
72251
|
finish(id, result) {
|
|
72204
72252
|
getDb().update(environmentBuilds).set({
|
|
@@ -72566,32 +72614,32 @@ ${this.text.slice(-MAX_LOG_BYTES)}`;
|
|
|
72566
72614
|
}
|
|
72567
72615
|
// ---- running ---------------------------------------------------------------
|
|
72568
72616
|
async run(row, plan) {
|
|
72569
|
-
const
|
|
72617
|
+
const log90 = new BuildLog(row.id, (id, text4) => this.queries.setLog(id, text4));
|
|
72570
72618
|
let tmp = null;
|
|
72571
72619
|
const container = `band-env-${row.id.slice(0, 12)}`;
|
|
72572
72620
|
let failure4 = null;
|
|
72573
72621
|
try {
|
|
72574
|
-
|
|
72575
|
-
|
|
72622
|
+
log90.add(`Building ${plan.tag} for ${plan.repo} at ${plan.ref} (${plan.commit.slice(0, 12)})`);
|
|
72623
|
+
log90.flush();
|
|
72576
72624
|
tmp = await plan.host.fs.mkdtemp("band-env-");
|
|
72577
|
-
await this.exportCheckout(plan, tmp,
|
|
72578
|
-
const toolchain = await this.buildToolchain(plan, tmp,
|
|
72579
|
-
const layered = await this.addWorkerLayer(plan, tmp, toolchain,
|
|
72580
|
-
await this.install(plan, tmp, layered, container,
|
|
72581
|
-
if (plan.registry) await this.push(plan,
|
|
72582
|
-
|
|
72625
|
+
await this.exportCheckout(plan, tmp, log90);
|
|
72626
|
+
const toolchain = await this.buildToolchain(plan, tmp, log90);
|
|
72627
|
+
const layered = await this.addWorkerLayer(plan, tmp, toolchain, log90);
|
|
72628
|
+
await this.install(plan, tmp, layered, container, log90);
|
|
72629
|
+
if (plan.registry) await this.push(plan, log90);
|
|
72630
|
+
log90.add(`Done: ${plan.tag}`);
|
|
72583
72631
|
} catch (err) {
|
|
72584
72632
|
failure4 = err.message;
|
|
72585
|
-
|
|
72633
|
+
log90.add(`FAILED: ${failure4}`);
|
|
72586
72634
|
}
|
|
72587
|
-
await this.exec(plan.host, "docker", ["rm", "--force", container],
|
|
72635
|
+
await this.exec(plan.host, "docker", ["rm", "--force", container], log90, { quiet: true }).catch(
|
|
72588
72636
|
() => void 0
|
|
72589
72637
|
);
|
|
72590
72638
|
await this.exec(
|
|
72591
72639
|
plan.host,
|
|
72592
72640
|
"docker",
|
|
72593
72641
|
["rmi", toolchainTag(plan.repo, plan.key), layeredTag(plan.repo, plan.key)],
|
|
72594
|
-
|
|
72642
|
+
log90,
|
|
72595
72643
|
{ quiet: true }
|
|
72596
72644
|
).catch(() => void 0);
|
|
72597
72645
|
if (tmp) await plan.host.fs.rm(tmp, { recursive: true, force: true }).catch(() => void 0);
|
|
@@ -72600,14 +72648,14 @@ ${this.text.slice(-MAX_LOG_BYTES)}`;
|
|
|
72600
72648
|
this.queries.finish(row.id, {
|
|
72601
72649
|
status: "ready",
|
|
72602
72650
|
image: plan.tag,
|
|
72603
|
-
log:
|
|
72651
|
+
log: log90.toString(),
|
|
72604
72652
|
at: Date.now()
|
|
72605
72653
|
});
|
|
72606
72654
|
} else {
|
|
72607
72655
|
this.queries.finish(row.id, {
|
|
72608
72656
|
status: "failed",
|
|
72609
72657
|
error: failure4.slice(0, 2e3),
|
|
72610
|
-
log:
|
|
72658
|
+
log: log90.toString(),
|
|
72611
72659
|
at: Date.now()
|
|
72612
72660
|
});
|
|
72613
72661
|
}
|
|
@@ -72616,9 +72664,9 @@ ${this.text.slice(-MAX_LOG_BYTES)}`;
|
|
|
72616
72664
|
}
|
|
72617
72665
|
}
|
|
72618
72666
|
/** Runs a command on the builder host, adding it and its output to the log. */
|
|
72619
|
-
async exec(host, tool, args,
|
|
72667
|
+
async exec(host, tool, args, log90, options = {}) {
|
|
72620
72668
|
const bin = tool === "docker" ? this.dockerBin(host) : tool === "devcontainer" ? this.devcontainerBin(host) : "git";
|
|
72621
|
-
if (!options.quiet)
|
|
72669
|
+
if (!options.quiet) log90.add(`$ ${tool} ${args.join(" ")}`);
|
|
72622
72670
|
try {
|
|
72623
72671
|
const out = await host.exec(bin, args, {
|
|
72624
72672
|
cwd: options.cwd,
|
|
@@ -72626,35 +72674,35 @@ ${this.text.slice(-MAX_LOG_BYTES)}`;
|
|
|
72626
72674
|
timeoutMs: envNumber("BAND_ENVIRONMENT_BUILD_TIMEOUT_MS", DEFAULT_STEP_TIMEOUT_MS)
|
|
72627
72675
|
});
|
|
72628
72676
|
if (!options.quiet) {
|
|
72629
|
-
if (out.stdout.trim())
|
|
72630
|
-
if (out.stderr.trim())
|
|
72631
|
-
|
|
72677
|
+
if (out.stdout.trim()) log90.add(out.stdout.trimEnd());
|
|
72678
|
+
if (out.stderr.trim()) log90.add(out.stderr.trimEnd());
|
|
72679
|
+
log90.flush();
|
|
72632
72680
|
}
|
|
72633
72681
|
return out.stdout;
|
|
72634
72682
|
} catch (err) {
|
|
72635
72683
|
if (!options.quiet) {
|
|
72636
|
-
|
|
72637
|
-
|
|
72684
|
+
log90.add(err.message);
|
|
72685
|
+
log90.flush();
|
|
72638
72686
|
}
|
|
72639
72687
|
throw new Error(`${tool} ${args[0] ?? ""} failed: ${firstLine(err.message)}`);
|
|
72640
72688
|
}
|
|
72641
72689
|
}
|
|
72642
72690
|
/** Writes the default branch's files, with no `.git`, to `<tmp>/src`. */
|
|
72643
|
-
async exportCheckout(plan, tmp,
|
|
72691
|
+
async exportCheckout(plan, tmp, log90) {
|
|
72644
72692
|
const src = posix4.join(tmp, "src");
|
|
72645
72693
|
await plan.host.fs.mkdir(src);
|
|
72646
72694
|
const index3 = posix4.join(tmp, "index");
|
|
72647
|
-
await this.exec(plan.host, "git", ["read-tree", plan.ref],
|
|
72695
|
+
await this.exec(plan.host, "git", ["read-tree", plan.ref], log90, {
|
|
72648
72696
|
cwd: plan.repoPath,
|
|
72649
72697
|
env: { GIT_INDEX_FILE: index3 }
|
|
72650
72698
|
});
|
|
72651
|
-
await this.exec(plan.host, "git", ["checkout-index", "--all", `--prefix=${src}/`],
|
|
72699
|
+
await this.exec(plan.host, "git", ["checkout-index", "--all", `--prefix=${src}/`], log90, {
|
|
72652
72700
|
cwd: plan.repoPath,
|
|
72653
72701
|
env: { GIT_INDEX_FILE: index3 }
|
|
72654
72702
|
});
|
|
72655
72703
|
}
|
|
72656
72704
|
/** Layer 2: returns the tag of an image holding the repo's toolchain. */
|
|
72657
|
-
async buildToolchain(plan, tmp,
|
|
72705
|
+
async buildToolchain(plan, tmp, log90) {
|
|
72658
72706
|
const build = plan.environment.build;
|
|
72659
72707
|
const src = posix4.join(tmp, "src");
|
|
72660
72708
|
const tag = toolchainTag(plan.repo, plan.key);
|
|
@@ -72663,7 +72711,7 @@ ${this.text.slice(-MAX_LOG_BYTES)}`;
|
|
|
72663
72711
|
plan.host,
|
|
72664
72712
|
"docker",
|
|
72665
72713
|
dockerBuildArgs({ checkout: src, dockerfile: build.dockerfile, tag }),
|
|
72666
|
-
|
|
72714
|
+
log90
|
|
72667
72715
|
);
|
|
72668
72716
|
return tag;
|
|
72669
72717
|
}
|
|
@@ -72673,7 +72721,7 @@ ${this.text.slice(-MAX_LOG_BYTES)}`;
|
|
|
72673
72721
|
plan.host,
|
|
72674
72722
|
"devcontainer",
|
|
72675
72723
|
devcontainerBuildArgs({ checkout: src, config: build.devcontainer, tag }),
|
|
72676
|
-
|
|
72724
|
+
log90
|
|
72677
72725
|
);
|
|
72678
72726
|
} catch (err) {
|
|
72679
72727
|
throw new Error(
|
|
@@ -72683,11 +72731,11 @@ ${this.text.slice(-MAX_LOG_BYTES)}`;
|
|
|
72683
72731
|
return tag;
|
|
72684
72732
|
}
|
|
72685
72733
|
const image = build?.image;
|
|
72686
|
-
await this.exec(plan.host, "docker", ["pull", image],
|
|
72734
|
+
await this.exec(plan.host, "docker", ["pull", image], log90);
|
|
72687
72735
|
return image;
|
|
72688
72736
|
}
|
|
72689
72737
|
/** Layer 1 on top of layer 2: copies the worker from the worker base image. */
|
|
72690
|
-
async addWorkerLayer(plan, tmp, toolchain,
|
|
72738
|
+
async addWorkerLayer(plan, tmp, toolchain, log90) {
|
|
72691
72739
|
const dir = posix4.join(tmp, "layer");
|
|
72692
72740
|
await plan.host.fs.mkdir(dir);
|
|
72693
72741
|
await plan.host.fs.writeFile(
|
|
@@ -72699,38 +72747,38 @@ ${this.text.slice(-MAX_LOG_BYTES)}`;
|
|
|
72699
72747
|
});
|
|
72700
72748
|
await plan.host.fs.mkdir(posix4.join(dir, "root", "work"), { recursive: true });
|
|
72701
72749
|
const tag = layeredTag(plan.repo, plan.key);
|
|
72702
|
-
await this.exec(plan.host, "docker", ["build", "--tag", tag, dir],
|
|
72750
|
+
await this.exec(plan.host, "docker", ["build", "--tag", tag, dir], log90);
|
|
72703
72751
|
return tag;
|
|
72704
72752
|
}
|
|
72705
72753
|
/** Runs `install` at the default branch inside the image and commits the result as the final tag. */
|
|
72706
|
-
async install(plan, tmp, layered, container,
|
|
72754
|
+
async install(plan, tmp, layered, container, log90) {
|
|
72707
72755
|
const install = plan.environment.install;
|
|
72708
72756
|
if (install === void 0) {
|
|
72709
|
-
await this.exec(plan.host, "docker", ["tag", layered, plan.tag],
|
|
72757
|
+
await this.exec(plan.host, "docker", ["tag", layered, plan.tag], log90);
|
|
72710
72758
|
return;
|
|
72711
72759
|
}
|
|
72712
72760
|
await this.exec(
|
|
72713
72761
|
plan.host,
|
|
72714
72762
|
"docker",
|
|
72715
72763
|
installCreateArgs({ name: container, image: layered, install }),
|
|
72716
|
-
|
|
72764
|
+
log90
|
|
72717
72765
|
);
|
|
72718
72766
|
await this.exec(
|
|
72719
72767
|
plan.host,
|
|
72720
72768
|
"docker",
|
|
72721
72769
|
["cp", `${posix4.join(tmp, "src")}/.`, `${container}:${IMAGE_WORKDIR}`],
|
|
72722
|
-
|
|
72770
|
+
log90
|
|
72723
72771
|
);
|
|
72724
|
-
await this.exec(plan.host, "docker", ["start", "--attach", container],
|
|
72772
|
+
await this.exec(plan.host, "docker", ["start", "--attach", container], log90);
|
|
72725
72773
|
await this.exec(
|
|
72726
72774
|
plan.host,
|
|
72727
72775
|
"docker",
|
|
72728
72776
|
commitArgs({ container, tag: plan.tag, key: plan.key, commit: plan.commit }),
|
|
72729
|
-
|
|
72777
|
+
log90
|
|
72730
72778
|
);
|
|
72731
72779
|
}
|
|
72732
|
-
async push(plan,
|
|
72733
|
-
await this.exec(plan.host, "docker", ["push", plan.tag],
|
|
72780
|
+
async push(plan, log90) {
|
|
72781
|
+
await this.exec(plan.host, "docker", ["push", plan.tag], log90);
|
|
72734
72782
|
}
|
|
72735
72783
|
// ---- auto trigger ----------------------------------------------------------
|
|
72736
72784
|
/**
|
|
@@ -75665,10 +75713,8 @@ var init_client_state_keys = __esm({
|
|
|
75665
75713
|
perWorktree("band:dockview-layout-v9:", [jsonPart("device")]),
|
|
75666
75714
|
// The `at` of the continuation the user has seen, which hides the sidebar clock icon.
|
|
75667
75715
|
perWorktree("band:continued-seen:", [rawPart("device")]),
|
|
75668
|
-
// The repo names the mobile app's worktree list has collapsed.
|
|
75716
|
+
// The repo and group names the mobile app's worktree list has collapsed.
|
|
75669
75717
|
exact("band.mobile.collapsed-repos", [jsonPart("device")]),
|
|
75670
|
-
// How the mobile worktree list is grouped: repo, origin or host.
|
|
75671
|
-
exact("band.mobile.group-by", [rawPart("device")]),
|
|
75672
75718
|
// The group the mobile worktree list is filtered to (a group id; unset means All).
|
|
75673
75719
|
exact("band.mobile.group-filter", [rawPart("device")])
|
|
75674
75720
|
];
|
|
@@ -75803,7 +75849,7 @@ var init_client_state_service = __esm({
|
|
|
75803
75849
|
}
|
|
75804
75850
|
const updatedAt = Date.now();
|
|
75805
75851
|
const version3 = input2.baseVersion + 1;
|
|
75806
|
-
|
|
75852
|
+
let written = input2.baseVersion === 0 ? this.queries.insertIfAbsent({
|
|
75807
75853
|
key: input2.key,
|
|
75808
75854
|
scope: input2.scope,
|
|
75809
75855
|
worktreeId: worktreeId4,
|
|
@@ -75815,6 +75861,16 @@ var init_client_state_service = __esm({
|
|
|
75815
75861
|
version: version3,
|
|
75816
75862
|
updatedAt
|
|
75817
75863
|
});
|
|
75864
|
+
if (!written && input2.baseVersion === 0) {
|
|
75865
|
+
const current3 = this.queries.find(input2.key, input2.scope);
|
|
75866
|
+
if (current3 && current3.value === null) {
|
|
75867
|
+
written = this.queries.updateIfVersion(input2.key, input2.scope, current3.version, {
|
|
75868
|
+
value,
|
|
75869
|
+
version: current3.version + 1,
|
|
75870
|
+
updatedAt
|
|
75871
|
+
});
|
|
75872
|
+
}
|
|
75873
|
+
}
|
|
75818
75874
|
const entry = this.queries.find(input2.key, input2.scope) ?? {
|
|
75819
75875
|
key: input2.key,
|
|
75820
75876
|
scope: input2.scope,
|
|
@@ -83233,7 +83289,7 @@ var init_agent_session_service = __esm({
|
|
|
83233
83289
|
ownerGrants.delete(chatId);
|
|
83234
83290
|
const grant = await worktree.host.relay?.issue({ worktreeId: chat.worktreeId, chatId });
|
|
83235
83291
|
if (grant) ownerGrants.set(chatId, grant);
|
|
83236
|
-
const shared2 = await openSharedDir(chat.worktreeId).catch(() => null);
|
|
83292
|
+
const shared2 = await openSharedDir(chat.worktreeId, chatId).catch(() => null);
|
|
83237
83293
|
const login = await agentLoginService.resolve({
|
|
83238
83294
|
agentType: def.type,
|
|
83239
83295
|
repo: worktree.repo.name,
|
|
@@ -88139,11 +88195,11 @@ var require_core = __commonJS({
|
|
|
88139
88195
|
Ajv2.ValidationError = validation_error_1.default;
|
|
88140
88196
|
Ajv2.MissingRefError = ref_error_1.default;
|
|
88141
88197
|
exports.default = Ajv2;
|
|
88142
|
-
function checkOptions(checkOpts, options, msg,
|
|
88198
|
+
function checkOptions(checkOpts, options, msg, log90 = "error") {
|
|
88143
88199
|
for (const key2 in checkOpts) {
|
|
88144
88200
|
const opt = key2;
|
|
88145
88201
|
if (opt in options)
|
|
88146
|
-
this.logger[
|
|
88202
|
+
this.logger[log90](`${msg}: option ${key2}. ${checkOpts[opt]}`);
|
|
88147
88203
|
}
|
|
88148
88204
|
}
|
|
88149
88205
|
function getSchEnv(keyRef) {
|
|
@@ -90632,10 +90688,11 @@ import {
|
|
|
90632
90688
|
existsSync as existsSync18,
|
|
90633
90689
|
mkdirSync as mkdirSync11,
|
|
90634
90690
|
readFileSync as readFileSync12,
|
|
90691
|
+
realpathSync as realpathSync7,
|
|
90635
90692
|
statSync as statSync16
|
|
90636
90693
|
} from "node:fs";
|
|
90637
90694
|
import { createServer as createServer3 } from "node:http";
|
|
90638
|
-
import { basename as basename7, join as
|
|
90695
|
+
import { basename as basename7, join as join58, resolve as resolve14, sep as sep10 } from "node:path";
|
|
90639
90696
|
import { pipeline as pipeline2, Readable as Readable2 } from "node:stream";
|
|
90640
90697
|
import { parseArgs } from "node:util";
|
|
90641
90698
|
|
|
@@ -111646,7 +111703,7 @@ init_registry();
|
|
|
111646
111703
|
// package.json
|
|
111647
111704
|
var package_default = {
|
|
111648
111705
|
name: "@band-app/server",
|
|
111649
|
-
version: "0.
|
|
111706
|
+
version: "0.54.1",
|
|
111650
111707
|
type: "module",
|
|
111651
111708
|
types: "src/index.ts",
|
|
111652
111709
|
exports: {
|
|
@@ -111686,6 +111743,7 @@ var package_default = {
|
|
|
111686
111743
|
"@agentclientprotocol/claude-agent-acp": "0.81.2",
|
|
111687
111744
|
"@agentclientprotocol/codex-acp": "1.13.1",
|
|
111688
111745
|
"@agentclientprotocol/sdk": "1.5.0",
|
|
111746
|
+
"@anthropic-ai/sdk": "1.1.0",
|
|
111689
111747
|
"@vscode/ripgrep": "^1.18.0",
|
|
111690
111748
|
"node-pty": "^1.1.0",
|
|
111691
111749
|
prettier: "^3.8.3",
|
|
@@ -112663,84 +112721,6 @@ init_git_credential_service();
|
|
|
112663
112721
|
init_placement_service();
|
|
112664
112722
|
init_token_service();
|
|
112665
112723
|
init_watcher_service();
|
|
112666
|
-
|
|
112667
|
-
// src/server/services/worker-cli-service.ts
|
|
112668
|
-
init_cli_binary();
|
|
112669
|
-
init_src7();
|
|
112670
|
-
init_src();
|
|
112671
|
-
import { createHash as createHash12 } from "node:crypto";
|
|
112672
|
-
import { readFile as readFile12 } from "node:fs/promises";
|
|
112673
|
-
import { join as join52 } from "node:path";
|
|
112674
|
-
var log65 = createLogger("worker-cli");
|
|
112675
|
-
var RPC_INVALID_PARAMS2 = -32602;
|
|
112676
|
-
var PLATFORM_NAME = /^[a-z0-9_]{1,16}$/;
|
|
112677
|
-
function candidatesFor(platform3, arch) {
|
|
112678
|
-
const out = [];
|
|
112679
|
-
const dir = process.env.BAND_CLI_BINARIES_DIR;
|
|
112680
|
-
if (dir) out.push(join52(dir, `band-${platform3}-${arch}${platform3 === "win32" ? ".exe" : ""}`));
|
|
112681
|
-
if (platform3 === process.platform && arch === process.arch) {
|
|
112682
|
-
const own2 = findCliBinary();
|
|
112683
|
-
if (own2) out.push(own2);
|
|
112684
|
-
}
|
|
112685
|
-
return out;
|
|
112686
|
-
}
|
|
112687
|
-
async function readFirst(paths) {
|
|
112688
|
-
for (const path2 of paths) {
|
|
112689
|
-
const data = await readFile12(path2).catch(() => null);
|
|
112690
|
-
if (data) return data;
|
|
112691
|
-
}
|
|
112692
|
-
return null;
|
|
112693
|
-
}
|
|
112694
|
-
var WorkerCliService = class {
|
|
112695
|
-
/** Answers `cli.fetch` on a worker's session. */
|
|
112696
|
-
attach(session) {
|
|
112697
|
-
session.handle(METHOD_CLI_FETCH, (params) => this.handle(session, params));
|
|
112698
|
-
}
|
|
112699
|
-
async handle(session, params) {
|
|
112700
|
-
const { platform: platform3, arch, have } = parseParams3(params);
|
|
112701
|
-
const data = await readFirst(candidatesFor(platform3, arch));
|
|
112702
|
-
if (!data) {
|
|
112703
|
-
return {
|
|
112704
|
-
available: false,
|
|
112705
|
-
reason: `the hub has no band CLI for ${platform3}-${arch}`
|
|
112706
|
-
};
|
|
112707
|
-
}
|
|
112708
|
-
const sha2563 = createHash12("sha256").update(data).digest("hex");
|
|
112709
|
-
if (have === sha2563) return { available: true, sha256: sha2563, size: data.length };
|
|
112710
|
-
log65.info(
|
|
112711
|
-
`sending the band CLI (${platform3}-${arch}, ${data.length} bytes) to ${session.workerId}`
|
|
112712
|
-
);
|
|
112713
|
-
const ch = session.openChannel("cli.body", { platform: platform3, arch });
|
|
112714
|
-
void (async () => {
|
|
112715
|
-
try {
|
|
112716
|
-
await ch.send(data);
|
|
112717
|
-
ch.end();
|
|
112718
|
-
const drained = setTimeout(() => ch.reset("the worker did not close the channel"), 3e4);
|
|
112719
|
-
drained.unref?.();
|
|
112720
|
-
await ch.readAll().finally(() => clearTimeout(drained));
|
|
112721
|
-
} catch (err) {
|
|
112722
|
-
ch.reset(err instanceof Error ? err.message : "cli transfer failed");
|
|
112723
|
-
}
|
|
112724
|
-
})();
|
|
112725
|
-
return { available: true, sha256: sha2563, size: data.length, chan: ch.id };
|
|
112726
|
-
}
|
|
112727
|
-
};
|
|
112728
|
-
function parseParams3(params) {
|
|
112729
|
-
const p2 = params ?? {};
|
|
112730
|
-
if (typeof p2.platform !== "string" || !PLATFORM_NAME.test(p2.platform)) {
|
|
112731
|
-
throw new RpcError(RPC_INVALID_PARAMS2, "platform must be a short lowercase name");
|
|
112732
|
-
}
|
|
112733
|
-
if (typeof p2.arch !== "string" || !PLATFORM_NAME.test(p2.arch)) {
|
|
112734
|
-
throw new RpcError(RPC_INVALID_PARAMS2, "arch must be a short lowercase name");
|
|
112735
|
-
}
|
|
112736
|
-
if (p2.have !== void 0 && typeof p2.have !== "string") {
|
|
112737
|
-
throw new RpcError(RPC_INVALID_PARAMS2, "have must be a string");
|
|
112738
|
-
}
|
|
112739
|
-
return { platform: p2.platform, arch: p2.arch, have: p2.have };
|
|
112740
|
-
}
|
|
112741
|
-
var workerCliService = new WorkerCliService();
|
|
112742
|
-
|
|
112743
|
-
// src/server/services/worker-link-service.ts
|
|
112744
112724
|
init_worker_lease_service();
|
|
112745
112725
|
|
|
112746
112726
|
// src/server/services/worker-relay-service.ts
|
|
@@ -112800,7 +112780,7 @@ function repoHostRefusal(repo, callerHostId) {
|
|
|
112800
112780
|
init_state();
|
|
112801
112781
|
init_subscription_service();
|
|
112802
112782
|
init_terminal_service();
|
|
112803
|
-
var
|
|
112783
|
+
var log65 = createLogger("worker-relay");
|
|
112804
112784
|
var REPLY_HEADERS = ["content-type", "cache-control", "mcp-session-id"];
|
|
112805
112785
|
var FORWARDED_HEADERS = [
|
|
112806
112786
|
"content-type",
|
|
@@ -112809,7 +112789,7 @@ var FORWARDED_HEADERS = [
|
|
|
112809
112789
|
"mcp-session-id",
|
|
112810
112790
|
"last-event-id"
|
|
112811
112791
|
];
|
|
112812
|
-
var
|
|
112792
|
+
var RPC_INVALID_PARAMS2 = -32602;
|
|
112813
112793
|
var defaultLookups = {
|
|
112814
112794
|
hostOfWorktree: (id) => hostRegistry.hostIdOfScope(id),
|
|
112815
112795
|
worktreeOfChat: (id) => {
|
|
@@ -112841,7 +112821,7 @@ var WorkerRelayService = class {
|
|
|
112841
112821
|
let request = parseRequest(params);
|
|
112842
112822
|
const verdict = checkRelayRequest(request, session.workerId, this.lookups);
|
|
112843
112823
|
if (!verdict.ok) {
|
|
112844
|
-
|
|
112824
|
+
log65.warn(
|
|
112845
112825
|
`refused ${request.method} ${request.path.split("?")[0]} from ${session.workerId}: ${verdict.reason}`
|
|
112846
112826
|
);
|
|
112847
112827
|
return this.answer(session, verdict.status, refusalBody(request, verdict));
|
|
@@ -112854,7 +112834,7 @@ var WorkerRelayService = class {
|
|
|
112854
112834
|
chatId: request.scope.chatId,
|
|
112855
112835
|
...entry
|
|
112856
112836
|
});
|
|
112857
|
-
|
|
112837
|
+
log65.info(
|
|
112858
112838
|
`admin host ${session.workerId} called ${entry.procedure}${entry.targetHostId ? ` on ${entry.targetHostId}` : ""}`
|
|
112859
112839
|
);
|
|
112860
112840
|
}
|
|
@@ -112887,7 +112867,7 @@ var WorkerRelayService = class {
|
|
|
112887
112867
|
redirect: "manual"
|
|
112888
112868
|
});
|
|
112889
112869
|
} catch (err) {
|
|
112890
|
-
|
|
112870
|
+
log65.warn(`relay call failed: ${err instanceof Error ? err.message : err}`);
|
|
112891
112871
|
return this.answer(session, 502, { error: "The hub could not answer" });
|
|
112892
112872
|
}
|
|
112893
112873
|
const replyHeaders = {};
|
|
@@ -112904,7 +112884,7 @@ var WorkerRelayService = class {
|
|
|
112904
112884
|
try {
|
|
112905
112885
|
return this.answer(session, upstream.status, redactSettingsReply(await upstream.json()));
|
|
112906
112886
|
} catch (err) {
|
|
112907
|
-
|
|
112887
|
+
log65.warn(`relay call failed: ${err instanceof Error ? err.message : err}`);
|
|
112908
112888
|
return this.answer(session, 502, { error: "The hub could not answer" });
|
|
112909
112889
|
}
|
|
112910
112890
|
}
|
|
@@ -112913,7 +112893,7 @@ var WorkerRelayService = class {
|
|
|
112913
112893
|
const filtered = filterReposReply(await upstream.json(), session.workerId);
|
|
112914
112894
|
return this.answer(session, upstream.status, filtered);
|
|
112915
112895
|
} catch (err) {
|
|
112916
|
-
|
|
112896
|
+
log65.warn(`relay call failed: ${err instanceof Error ? err.message : err}`);
|
|
112917
112897
|
return this.answer(session, 502, { error: "The hub could not answer" });
|
|
112918
112898
|
}
|
|
112919
112899
|
}
|
|
@@ -112921,7 +112901,7 @@ var WorkerRelayService = class {
|
|
|
112921
112901
|
try {
|
|
112922
112902
|
return this.answer(session, upstream.status, redactHostsReply(await upstream.json()));
|
|
112923
112903
|
} catch (err) {
|
|
112924
|
-
|
|
112904
|
+
log65.warn(`relay call failed: ${err instanceof Error ? err.message : err}`);
|
|
112925
112905
|
return this.answer(session, 502, { error: "The hub could not answer" });
|
|
112926
112906
|
}
|
|
112927
112907
|
}
|
|
@@ -112966,7 +112946,7 @@ function parseRequest(params) {
|
|
|
112966
112946
|
const p2 = params;
|
|
112967
112947
|
const scope3 = p2?.scope;
|
|
112968
112948
|
if (!p2 || typeof p2.method !== "string" || typeof p2.path !== "string" || typeof scope3?.worktreeId !== "string" || scope3.chatId !== void 0 && typeof scope3.chatId !== "string" || scope3.terminalId !== void 0 && typeof scope3.terminalId !== "string" || !/^\/(?![/\\])/.test(p2.path) || !["GET", "POST", "DELETE", "OPTIONS", "HEAD"].includes(p2.method) || typeof p2.headers !== "object" || p2.headers === null || Object.values(p2.headers).some((v2) => typeof v2 !== "string") || p2.body !== void 0 && typeof p2.body !== "string") {
|
|
112969
|
-
throw new RpcError(
|
|
112949
|
+
throw new RpcError(RPC_INVALID_PARAMS2, "bad relay.http params");
|
|
112970
112950
|
}
|
|
112971
112951
|
return p2;
|
|
112972
112952
|
}
|
|
@@ -112974,7 +112954,7 @@ var workerRelayService = new WorkerRelayService();
|
|
|
112974
112954
|
|
|
112975
112955
|
// src/server/services/worker-link-service.ts
|
|
112976
112956
|
init_worktree_service();
|
|
112977
|
-
var
|
|
112957
|
+
var log66 = createLogger("worker-link");
|
|
112978
112958
|
var repoQueries5 = new RepoQueries();
|
|
112979
112959
|
var LOCAL_HOST_ID12 = "local";
|
|
112980
112960
|
var CAPABILITY_REFRESH_MS = 3 * 6e4;
|
|
@@ -113002,9 +112982,18 @@ var WorkerLinkService = class {
|
|
|
113002
112982
|
this.server = new LinkServer({ authenticate: (hello) => this.authenticate(hello) });
|
|
113003
112983
|
this.server.on("session", (session) => this.onSession(session));
|
|
113004
112984
|
this.server.on("connected", (session) => void this.onConnected(session));
|
|
112985
|
+
this.server.on("disconnected", (session) => {
|
|
112986
|
+
const close = session.lastClose;
|
|
112987
|
+
if (close) {
|
|
112988
|
+
log66.info(
|
|
112989
|
+
`link of ${session.workerId} closed (code ${close.code}${close.reason ? `, ${close.reason}` : ""})`
|
|
112990
|
+
);
|
|
112991
|
+
}
|
|
112992
|
+
this.setStatus(session.workerId, "offline", this.now());
|
|
112993
|
+
});
|
|
113005
112994
|
this.server.on(
|
|
113006
|
-
"
|
|
113007
|
-
(session) =>
|
|
112995
|
+
"fault",
|
|
112996
|
+
(session, reason) => log66.warn(`link of ${session.workerId}: ${reason}`)
|
|
113008
112997
|
);
|
|
113009
112998
|
this.server.on(
|
|
113010
112999
|
"lost",
|
|
@@ -113029,12 +113018,12 @@ var WorkerLinkService = class {
|
|
|
113029
113018
|
const problem2 = compatibilityProblem(version3, HUB_VERSION);
|
|
113030
113019
|
if (!problem2) return auth2;
|
|
113031
113020
|
if (HUB_VERSION_UNRELEASED) {
|
|
113032
|
-
|
|
113021
|
+
log66.info(
|
|
113033
113022
|
`worker ${hello.workerId} runs ${version3}, which would be refused by a released hub, but this hub runs from source (${HUB_VERSION}), so version checks are skipped`
|
|
113034
113023
|
);
|
|
113035
113024
|
return auth2;
|
|
113036
113025
|
}
|
|
113037
|
-
|
|
113026
|
+
log66.warn(`worker ${hello.workerId} refused: ${problem2}`);
|
|
113038
113027
|
if (this.server.getSession(hello.workerId)?.attached) {
|
|
113039
113028
|
return { ok: false, reason: problem2, code: VERSION_REFUSED_CODE };
|
|
113040
113029
|
}
|
|
@@ -113045,7 +113034,7 @@ var WorkerLinkService = class {
|
|
|
113045
113034
|
try {
|
|
113046
113035
|
this.queries.setHostRefusal(hello.workerId, { version: version3, reason: problem2 });
|
|
113047
113036
|
} catch (err) {
|
|
113048
|
-
|
|
113037
|
+
log66.warn(`could not record the refusal: ${err instanceof Error ? err.message : err}`);
|
|
113049
113038
|
}
|
|
113050
113039
|
this.publish(hello.workerId, "offline");
|
|
113051
113040
|
return { ok: false, reason: problem2, code: VERSION_REFUSED_CODE };
|
|
@@ -113068,7 +113057,7 @@ var WorkerLinkService = class {
|
|
|
113068
113057
|
this.refreshTimer.unref();
|
|
113069
113058
|
this.unsubscribeRevoke = this.tokens.onRevoked((row) => {
|
|
113070
113059
|
if (row.kind === "worker_session" && row.hostId) {
|
|
113071
|
-
if (this.server.drop(row.hostId, "token revoked"))
|
|
113060
|
+
if (this.server.drop(row.hostId, "token revoked")) log66.info(`cut link of ${row.hostId}`);
|
|
113072
113061
|
}
|
|
113073
113062
|
});
|
|
113074
113063
|
}
|
|
@@ -113098,7 +113087,7 @@ var WorkerLinkService = class {
|
|
|
113098
113087
|
this.queries.setHostInfo(row.id, stored);
|
|
113099
113088
|
if (changed) this.publish(row.id, "online");
|
|
113100
113089
|
} catch (err) {
|
|
113101
|
-
|
|
113090
|
+
log66.debug(
|
|
113102
113091
|
`could not refresh the report of ${row.id}: ${err instanceof Error ? err.message : err}`
|
|
113103
113092
|
);
|
|
113104
113093
|
}
|
|
@@ -113128,7 +113117,6 @@ var WorkerLinkService = class {
|
|
|
113128
113117
|
onSession(session) {
|
|
113129
113118
|
this.remoteHost(session.workerId).attachSession(session);
|
|
113130
113119
|
workerRelayService.attach(session);
|
|
113131
|
-
workerCliService.attach(session);
|
|
113132
113120
|
gitCredentialService.attach(session);
|
|
113133
113121
|
ephemeralLifecycleService.attach(session);
|
|
113134
113122
|
checkpointService.attach(session);
|
|
@@ -113142,7 +113130,7 @@ var WorkerLinkService = class {
|
|
|
113142
113130
|
try {
|
|
113143
113131
|
info = await this.remoteHost(workerId).info();
|
|
113144
113132
|
} catch (err) {
|
|
113145
|
-
|
|
113133
|
+
log66.warn(
|
|
113146
113134
|
`could not read host info from ${workerId}: ${err instanceof Error ? err.message : err}`
|
|
113147
113135
|
);
|
|
113148
113136
|
}
|
|
@@ -113162,37 +113150,37 @@ var WorkerLinkService = class {
|
|
|
113162
113150
|
const version3 = workerVersionOf(hello);
|
|
113163
113151
|
this.queries.markHostOnline(workerId, at, { info: stored, version: version3 ?? hello.buildId });
|
|
113164
113152
|
workerUpdateService.onConnected(workerId, version3);
|
|
113165
|
-
|
|
113153
|
+
log66.info(`worker ${workerId} is online`);
|
|
113166
113154
|
workerLeaseService.onConnected(session);
|
|
113167
113155
|
try {
|
|
113168
113156
|
seedCodingAgentsFromTypes(hello.agents);
|
|
113169
113157
|
} catch (err) {
|
|
113170
|
-
|
|
113158
|
+
log66.warn(`could not seed coding agents: ${err instanceof Error ? err.message : err}`);
|
|
113171
113159
|
}
|
|
113172
113160
|
this.publish(workerId, "online");
|
|
113173
113161
|
void repoService.backfillRemotesFromWorker(workerId).catch((err) => {
|
|
113174
|
-
|
|
113162
|
+
log66.warn(`remote backfill on ${workerId}: ${err instanceof Error ? err.message : err}`);
|
|
113175
113163
|
});
|
|
113176
113164
|
chatOwnershipService.onConnected(session);
|
|
113177
113165
|
void ephemeralLifecycleService.onConnected(session);
|
|
113178
113166
|
void followService.onHostReturned(workerId).catch((err) => {
|
|
113179
|
-
|
|
113167
|
+
log66.warn(`follow check on ${workerId}: ${err instanceof Error ? err.message : err}`);
|
|
113180
113168
|
});
|
|
113181
113169
|
placementService.onHostOnline(workerId);
|
|
113182
113170
|
void worktreeService.finishPendingRemovals(workerId).catch((err) => {
|
|
113183
|
-
|
|
113171
|
+
log66.warn(`pending removals on ${workerId}: ${err instanceof Error ? err.message : err}`);
|
|
113184
113172
|
});
|
|
113185
113173
|
}
|
|
113186
113174
|
setStatus(workerId, status, lastSeenAt) {
|
|
113187
113175
|
try {
|
|
113188
113176
|
this.queries.setHostStatus(workerId, status, lastSeenAt);
|
|
113189
113177
|
} catch (err) {
|
|
113190
|
-
|
|
113178
|
+
log66.warn(
|
|
113191
113179
|
`could not record ${workerId} as ${status}: ${err instanceof Error ? err.message : err}`
|
|
113192
113180
|
);
|
|
113193
113181
|
return;
|
|
113194
113182
|
}
|
|
113195
|
-
|
|
113183
|
+
log66.info(`worker ${workerId} is ${status}`);
|
|
113196
113184
|
this.publish(workerId, status);
|
|
113197
113185
|
}
|
|
113198
113186
|
publish(hostId2, hostStatus) {
|
|
@@ -113237,7 +113225,7 @@ var WorkerLinkService = class {
|
|
|
113237
113225
|
send3(200, out);
|
|
113238
113226
|
} catch (err) {
|
|
113239
113227
|
if (!(err instanceof TokenExchangeError)) throw err;
|
|
113240
|
-
|
|
113228
|
+
log66.warn(`bootstrap exchange refused: ${err.reason}`);
|
|
113241
113229
|
send3(401, { error: "invalid or expired token" });
|
|
113242
113230
|
}
|
|
113243
113231
|
}
|
|
@@ -113254,7 +113242,7 @@ function reportKey(report2) {
|
|
|
113254
113242
|
|
|
113255
113243
|
// src/server/services/worker-update-service.ts
|
|
113256
113244
|
init_worktree_service();
|
|
113257
|
-
var
|
|
113245
|
+
var log67 = createLogger("worker-update");
|
|
113258
113246
|
var INSTALL_TIMEOUT_MS = 11 * 6e4;
|
|
113259
113247
|
var RESTART_TIMEOUT_MS = 3 * 6e4;
|
|
113260
113248
|
var WorkerUpdateError = class extends Error {
|
|
@@ -113300,7 +113288,7 @@ var WorkerUpdateService = class {
|
|
|
113300
113288
|
throw new WorkerUpdateError("not-updatable", "The worker is not connected");
|
|
113301
113289
|
const target = view4.updateTarget;
|
|
113302
113290
|
this.set(hostId2, { target, state: "installing", error: null }, row.status);
|
|
113303
|
-
|
|
113291
|
+
log67.info(`updating worker ${hostId2} to ${target}`);
|
|
113304
113292
|
void this.run(hostId2, target, session, row.status);
|
|
113305
113293
|
return { target };
|
|
113306
113294
|
}
|
|
@@ -113314,7 +113302,7 @@ var WorkerUpdateService = class {
|
|
|
113314
113302
|
} catch (err) {
|
|
113315
113303
|
const message = this.describe(err, target);
|
|
113316
113304
|
this.set(hostId2, { target, state: "failed", error: message }, hostStatus);
|
|
113317
|
-
|
|
113305
|
+
log67.warn(`update of worker ${hostId2} failed: ${message}`);
|
|
113318
113306
|
return;
|
|
113319
113307
|
}
|
|
113320
113308
|
if (this.updates.get(hostId2)?.state !== "installing") return;
|
|
@@ -113351,7 +113339,7 @@ var WorkerUpdateService = class {
|
|
|
113351
113339
|
this.timers.delete(hostId2);
|
|
113352
113340
|
if (version3 === current3.target) {
|
|
113353
113341
|
this.updates.delete(hostId2);
|
|
113354
|
-
|
|
113342
|
+
log67.info(`worker ${hostId2} now runs ${version3}`);
|
|
113355
113343
|
} else {
|
|
113356
113344
|
this.set(
|
|
113357
113345
|
hostId2,
|
|
@@ -116176,9 +116164,9 @@ init_zod();
|
|
|
116176
116164
|
// src/server/services/provisioning-service.ts
|
|
116177
116165
|
init_src();
|
|
116178
116166
|
init_dist();
|
|
116179
|
-
import { createHash as
|
|
116167
|
+
import { createHash as createHash12, randomBytes as randomBytes16, randomUUID as randomUUID18 } from "node:crypto";
|
|
116180
116168
|
import { createReadStream as createReadStream4, existsSync as existsSync17, mkdirSync as mkdirSync10, rmSync as rmSync7, statSync as statSync14 } from "node:fs";
|
|
116181
|
-
import { join as
|
|
116169
|
+
import { join as join52 } from "node:path";
|
|
116182
116170
|
|
|
116183
116171
|
// src/server/infra/db/queries/provisions.ts
|
|
116184
116172
|
init_drizzle_orm2();
|
|
@@ -116205,11 +116193,11 @@ var ProvisionQueries = class {
|
|
|
116205
116193
|
const result = this.db().update(hostProvisions).set({ spentAt: at, hostId: hostId2, runHash, state: "running", updatedAt: at }).where(and2(eq2(hostProvisions.id, id), isNull2(hostProvisions.spentAt))).run();
|
|
116206
116194
|
return Number(result.changes ?? 0) > 0;
|
|
116207
116195
|
}
|
|
116208
|
-
setLog(id,
|
|
116209
|
-
this.db().update(hostProvisions).set({ log:
|
|
116196
|
+
setLog(id, log90, at) {
|
|
116197
|
+
this.db().update(hostProvisions).set({ log: log90, updatedAt: at }).where(eq2(hostProvisions.id, id)).run();
|
|
116210
116198
|
}
|
|
116211
|
-
finish(id, state2, exitCode,
|
|
116212
|
-
this.db().update(hostProvisions).set({ state: state2, exitCode, log:
|
|
116199
|
+
finish(id, state2, exitCode, log90, at) {
|
|
116200
|
+
this.db().update(hostProvisions).set({ state: state2, exitCode, log: log90, updatedAt: at }).where(eq2(hostProvisions.id, id)).run();
|
|
116213
116201
|
}
|
|
116214
116202
|
/** Ids of rows created before `at`, so their bundle files can be deleted. */
|
|
116215
116203
|
idsCreatedBefore(at) {
|
|
@@ -116461,7 +116449,7 @@ function renderProvisionScript(opts) {
|
|
|
116461
116449
|
init_settings_service();
|
|
116462
116450
|
init_token_service();
|
|
116463
116451
|
init_vault_service();
|
|
116464
|
-
var
|
|
116452
|
+
var log68 = createLogger("provisioning");
|
|
116465
116453
|
var DEFAULT_PROVISION_TTL_MS = 60 * 60 * 1e3;
|
|
116466
116454
|
var DEFAULT_START_COMMAND = "band/provision.sh";
|
|
116467
116455
|
var MAX_LOG_BYTES2 = 256 * 1024;
|
|
@@ -116493,7 +116481,7 @@ var ProvisionAuthError = class extends Error {
|
|
|
116493
116481
|
}
|
|
116494
116482
|
};
|
|
116495
116483
|
function sha2562(text4) {
|
|
116496
|
-
return
|
|
116484
|
+
return createHash12("sha256").update(text4).digest("hex");
|
|
116497
116485
|
}
|
|
116498
116486
|
function newSecret(prefix) {
|
|
116499
116487
|
return `${prefix}${randomBytes16(32).toString("base64url")}`;
|
|
@@ -116536,7 +116524,7 @@ var ProvisioningService = class {
|
|
|
116536
116524
|
return Date.now();
|
|
116537
116525
|
}
|
|
116538
116526
|
dir(id) {
|
|
116539
|
-
return
|
|
116527
|
+
return join52(bandHome(), "provisioning", id);
|
|
116540
116528
|
}
|
|
116541
116529
|
settings() {
|
|
116542
116530
|
const s2 = settingsService.get().provisioning ?? {};
|
|
@@ -116591,7 +116579,7 @@ var ProvisioningService = class {
|
|
|
116591
116579
|
spentAt: null,
|
|
116592
116580
|
updatedAt: at
|
|
116593
116581
|
});
|
|
116594
|
-
|
|
116582
|
+
log68.info(
|
|
116595
116583
|
`created provisioning command ${id}${commitSha ? ` at ${commitSha.slice(0, 12)}` : ""}`
|
|
116596
116584
|
);
|
|
116597
116585
|
const command2 = `curl -fsSL ${hubUrl}/api/provision/${code}/script | sh`;
|
|
@@ -116631,7 +116619,7 @@ var ProvisioningService = class {
|
|
|
116631
116619
|
tokenService.removeHost(boot.hostId);
|
|
116632
116620
|
throw new ProvisionExchangeError("used");
|
|
116633
116621
|
}
|
|
116634
|
-
|
|
116622
|
+
log68.info(`exchanged provisioning code ${row.id} for host ${boot.hostId}`);
|
|
116635
116623
|
const lines = [
|
|
116636
116624
|
`token=${boot.token}`,
|
|
116637
116625
|
`workerId=${boot.hostId}`,
|
|
@@ -116656,7 +116644,7 @@ var ProvisioningService = class {
|
|
|
116656
116644
|
/** The bundle file and size for a code, once its run token is shown. */
|
|
116657
116645
|
bundle(code, runToken) {
|
|
116658
116646
|
const row = this.authorize(code, runToken);
|
|
116659
|
-
const file3 =
|
|
116647
|
+
const file3 = join52(this.dir(row.id), "bundle.tgz");
|
|
116660
116648
|
if (!row.repoUrl || !existsSync17(file3)) throw new ProvisionAuthError();
|
|
116661
116649
|
return { stream: createReadStream4(file3), size: statSync14(file3).size };
|
|
116662
116650
|
}
|
|
@@ -116673,7 +116661,7 @@ var ProvisioningService = class {
|
|
|
116673
116661
|
return;
|
|
116674
116662
|
}
|
|
116675
116663
|
this.queries.finish(row.id, exit === 0 ? "done" : "failed", exit, next, at);
|
|
116676
|
-
if (exit !== 0)
|
|
116664
|
+
if (exit !== 0) log68.info(`provisioning ${row.id} failed with exit code ${exit}`);
|
|
116677
116665
|
}
|
|
116678
116666
|
status(id) {
|
|
116679
116667
|
const row = this.queries.findById(id);
|
|
@@ -116698,7 +116686,7 @@ band provision: the worker did not say hello within ${minutes} min. Marked faile
|
|
|
116698
116686
|
`;
|
|
116699
116687
|
const exitCode = row.exitCode ?? TIMEOUT_EXIT_CODE;
|
|
116700
116688
|
this.queries.finish(row.id, "failed", exitCode, row.log + note, at);
|
|
116701
|
-
|
|
116689
|
+
log68.info(`provisioning ${row.id} timed out waiting for host ${row.hostId}`);
|
|
116702
116690
|
return { ...row, state: "failed", exitCode, log: row.log + note };
|
|
116703
116691
|
}
|
|
116704
116692
|
view(spent) {
|
|
@@ -116735,7 +116723,7 @@ band provision: the worker did not say hello within ${minutes} min. Marked faile
|
|
|
116735
116723
|
async buildBundle(id, settings3) {
|
|
116736
116724
|
const dir = this.dir(id);
|
|
116737
116725
|
mkdirSync10(dir, { recursive: true });
|
|
116738
|
-
const src =
|
|
116726
|
+
const src = join52(dir, "src");
|
|
116739
116727
|
const host = hostRegistry.local;
|
|
116740
116728
|
const env = { GIT_TERMINAL_PROMPT: "0" };
|
|
116741
116729
|
const key2 = parseRemoteUrl2(settings3.repoUrl);
|
|
@@ -116757,10 +116745,10 @@ band provision: the worker did not say hello within ${minutes} min. Marked faile
|
|
|
116757
116745
|
await host.exec("git", args, { env, timeoutMs: 12e4 });
|
|
116758
116746
|
const sha = (await host.exec("git", ["-C", src, "rev-parse", "HEAD"], { env })).stdout.trim();
|
|
116759
116747
|
const command2 = settings3.command || DEFAULT_START_COMMAND;
|
|
116760
|
-
if (!existsSync17(
|
|
116748
|
+
if (!existsSync17(join52(src, command2))) {
|
|
116761
116749
|
throw new Error(`the repo at ${sha.slice(0, 12)} has no ${command2}`);
|
|
116762
116750
|
}
|
|
116763
|
-
await host.exec("tar", ["-czf",
|
|
116751
|
+
await host.exec("tar", ["-czf", join52(dir, "bundle.tgz"), "--exclude=.git", "-C", src, "."], {
|
|
116764
116752
|
timeoutMs: 12e4
|
|
116765
116753
|
});
|
|
116766
116754
|
rmSync7(src, { recursive: true, force: true });
|
|
@@ -116853,12 +116841,12 @@ init_zod();
|
|
|
116853
116841
|
init_registry();
|
|
116854
116842
|
init_queued_message_store();
|
|
116855
116843
|
import { realpathSync as realpathSync6 } from "node:fs";
|
|
116856
|
-
import { join as
|
|
116844
|
+
import { join as join53, resolve as resolve11, sep as sep7 } from "node:path";
|
|
116857
116845
|
init_chat_ownership_service();
|
|
116858
116846
|
init_chat_service();
|
|
116859
116847
|
init_state();
|
|
116860
116848
|
init_task_service();
|
|
116861
|
-
var
|
|
116849
|
+
var log69 = createLogger("trpc.queue");
|
|
116862
116850
|
var queuedFileSchema = external_exports2.object({
|
|
116863
116851
|
mediaType: external_exports2.string(),
|
|
116864
116852
|
url: external_exports2.string(),
|
|
@@ -116866,7 +116854,7 @@ var queuedFileSchema = external_exports2.object({
|
|
|
116866
116854
|
filename: external_exports2.string().optional()
|
|
116867
116855
|
});
|
|
116868
116856
|
function isPathWithinUploadDir(p2) {
|
|
116869
|
-
const uploadDir =
|
|
116857
|
+
const uploadDir = join53(bandHome(), "uploads");
|
|
116870
116858
|
const normalized2 = resolve11(p2);
|
|
116871
116859
|
if (normalized2 !== uploadDir && !normalized2.startsWith(uploadDir + sep7)) {
|
|
116872
116860
|
return false;
|
|
@@ -116891,7 +116879,7 @@ async function resolveQueuedFiles(chatId, worktreeId4, files) {
|
|
|
116891
116879
|
if (derivedPath) {
|
|
116892
116880
|
const inside = remote ? await isWithinUploads(worktreeId4, derivedPath) : isPathWithinUploadDir(derivedPath);
|
|
116893
116881
|
if (!inside) {
|
|
116894
|
-
|
|
116882
|
+
log69.warn(
|
|
116895
116883
|
{ chatId, path: derivedPath, filename: file3.filename },
|
|
116896
116884
|
"queue: dropping file with path outside uploads directory"
|
|
116897
116885
|
);
|
|
@@ -116916,7 +116904,7 @@ async function resolveQueuedFiles(chatId, worktreeId4, files) {
|
|
|
116916
116904
|
});
|
|
116917
116905
|
continue;
|
|
116918
116906
|
}
|
|
116919
|
-
|
|
116907
|
+
log69.warn(
|
|
116920
116908
|
{ chatId, url: file3.url, filename: file3.filename },
|
|
116921
116909
|
"queue: dropping file with no path and non-data URL \u2014 cannot recover disk path"
|
|
116922
116910
|
);
|
|
@@ -116924,7 +116912,7 @@ async function resolveQueuedFiles(chatId, worktreeId4, files) {
|
|
|
116924
116912
|
if (needsSave.length > 0) {
|
|
116925
116913
|
const saved = await saveWorktreeUploads(worktreeId4, needsSave);
|
|
116926
116914
|
if (saved.length !== needsSave.length) {
|
|
116927
|
-
|
|
116915
|
+
log69.error(
|
|
116928
116916
|
{ chatId, expected: needsSave.length, got: saved.length },
|
|
116929
116917
|
"queue: saveUploadedFilesDetailed returned unexpected count \u2014 dropping data-URL files (cannot map 1:1)"
|
|
116930
116918
|
);
|
|
@@ -116957,7 +116945,7 @@ var queueRouter = t.router({
|
|
|
116957
116945
|
try {
|
|
116958
116946
|
files = await resolveQueuedFiles(chatId, input2.worktreeId, input2.files);
|
|
116959
116947
|
} catch (err) {
|
|
116960
|
-
|
|
116948
|
+
log69.error(
|
|
116961
116949
|
{ chatId, err: err instanceof Error ? err.message : err },
|
|
116962
116950
|
"queue.push: failed to persist file uploads; enqueuing text only"
|
|
116963
116951
|
);
|
|
@@ -117007,7 +116995,7 @@ var queueRouter = t.router({
|
|
|
117007
116995
|
files: await resolveQueuedFiles(chatId, input2.worktreeId, m2.files)
|
|
117008
116996
|
};
|
|
117009
116997
|
} catch (err) {
|
|
117010
|
-
|
|
116998
|
+
log69.error(
|
|
117011
116999
|
{ chatId, messageId: m2.id, err: err instanceof Error ? err.message : err },
|
|
117012
117000
|
"queue: failed to resolve files for queued message; dropping its files"
|
|
117013
117001
|
);
|
|
@@ -117164,7 +117152,7 @@ function aggregateTurnsByHourAndModel(snap, provider) {
|
|
|
117164
117152
|
}
|
|
117165
117153
|
return Array.from(buckets.values());
|
|
117166
117154
|
}
|
|
117167
|
-
var
|
|
117155
|
+
var log70 = createLogger("usage-scanner");
|
|
117168
117156
|
var SCHEDULER_KEY2 = Symbol.for("band.usage-scanner");
|
|
117169
117157
|
var g7 = globalThis;
|
|
117170
117158
|
if (!g7[SCHEDULER_KEY2]) {
|
|
@@ -117226,14 +117214,14 @@ var UsageScannerService = class {
|
|
|
117226
117214
|
try {
|
|
117227
117215
|
totalRows += await this.scanPair(ws, a);
|
|
117228
117216
|
} catch (err) {
|
|
117229
|
-
|
|
117217
|
+
log70.warn(
|
|
117230
117218
|
{ err, worktreeId: ws.worktreeId, agentType: a.agentType },
|
|
117231
117219
|
"usage scanner pair failed"
|
|
117232
117220
|
);
|
|
117233
117221
|
}
|
|
117234
117222
|
}
|
|
117235
117223
|
}
|
|
117236
|
-
|
|
117224
|
+
log70.debug(
|
|
117237
117225
|
{ durationMs: this.now() - started, worktrees: worktrees2.length, rowsWritten: totalRows },
|
|
117238
117226
|
"usage scanner tick complete"
|
|
117239
117227
|
);
|
|
@@ -117278,7 +117266,7 @@ var UsageScannerService = class {
|
|
|
117278
117266
|
try {
|
|
117279
117267
|
reader = await this.getUsageReader(a, ws.hostId);
|
|
117280
117268
|
} catch (err) {
|
|
117281
|
-
|
|
117269
|
+
log70.debug({ err, agentId: a.agentId }, "failed to resolve usage reader for scan");
|
|
117282
117270
|
return 0;
|
|
117283
117271
|
}
|
|
117284
117272
|
if (!reader) return 0;
|
|
@@ -117287,7 +117275,7 @@ var UsageScannerService = class {
|
|
|
117287
117275
|
try {
|
|
117288
117276
|
sessions = await reader.listSessions(ws.worktreePath);
|
|
117289
117277
|
} catch (err) {
|
|
117290
|
-
|
|
117278
|
+
log70.debug(
|
|
117291
117279
|
{ err, agentId: a.agentId, worktreePath: ws.worktreePath },
|
|
117292
117280
|
"listSessions failed during usage scan"
|
|
117293
117281
|
);
|
|
@@ -117303,7 +117291,7 @@ var UsageScannerService = class {
|
|
|
117303
117291
|
try {
|
|
117304
117292
|
snap = await reader.getSessionUsage(s2.sessionId, ws.worktreePath);
|
|
117305
117293
|
} catch (err) {
|
|
117306
|
-
|
|
117294
|
+
log70.debug(
|
|
117307
117295
|
{ err, sessionId: s2.sessionId, agentType: a.agentType },
|
|
117308
117296
|
"getSessionUsage failed"
|
|
117309
117297
|
);
|
|
@@ -117342,7 +117330,7 @@ var UsageScannerService = class {
|
|
|
117342
117330
|
this.scanState.set(ws.worktreeId, a.agentType, maxObserved);
|
|
117343
117331
|
}
|
|
117344
117332
|
if (changed.length > slice.length) {
|
|
117345
|
-
|
|
117333
|
+
log70.debug(
|
|
117346
117334
|
{
|
|
117347
117335
|
worktreeId: ws.worktreeId,
|
|
117348
117336
|
agentType: a.agentType,
|
|
@@ -117409,11 +117397,11 @@ function startUsageScanner(options = {}) {
|
|
|
117409
117397
|
const intervalMs = options.intervalMs ?? USAGE_SCAN_INTERVAL_MS;
|
|
117410
117398
|
const svc = getUsageScannerService();
|
|
117411
117399
|
svc.tick().catch((err) => {
|
|
117412
|
-
|
|
117400
|
+
log70.warn({ err }, "initial usage scanner tick failed");
|
|
117413
117401
|
});
|
|
117414
117402
|
const timer = setInterval(() => {
|
|
117415
117403
|
svc.tick().catch((err) => {
|
|
117416
|
-
|
|
117404
|
+
log70.warn({ err }, "scheduled usage scanner tick failed");
|
|
117417
117405
|
});
|
|
117418
117406
|
}, intervalMs);
|
|
117419
117407
|
timer.unref();
|
|
@@ -117784,7 +117772,7 @@ function worktreeGh(host, localHostId, cwd) {
|
|
|
117784
117772
|
init_branch_status_poller();
|
|
117785
117773
|
init_plugin_host_service();
|
|
117786
117774
|
init_worktree_service();
|
|
117787
|
-
var
|
|
117775
|
+
var log71 = createLogger("review-service");
|
|
117788
117776
|
var NoOpenReviewError = class extends Error {
|
|
117789
117777
|
constructor(worktreeId4) {
|
|
117790
117778
|
super(`No open review to merge for worktree ${worktreeId4}`);
|
|
@@ -117825,7 +117813,7 @@ var ReviewService = class {
|
|
|
117825
117813
|
};
|
|
117826
117814
|
} catch (err) {
|
|
117827
117815
|
const message = err instanceof Error ? err.message : String(err);
|
|
117828
|
-
|
|
117816
|
+
log71.warn("Review lookup failed for %s (%s): %s", worktreeId4, provider.id, message);
|
|
117829
117817
|
return { status: "error", message };
|
|
117830
117818
|
}
|
|
117831
117819
|
}
|
|
@@ -117990,7 +117978,7 @@ init_ephemeral_lifecycle_service();
|
|
|
117990
117978
|
init_runner_service();
|
|
117991
117979
|
init_state();
|
|
117992
117980
|
init_token_service();
|
|
117993
|
-
var
|
|
117981
|
+
var log72 = createLogger("reaper");
|
|
117994
117982
|
var DEFAULT_INTERVAL_MS = 3e4;
|
|
117995
117983
|
var DEFAULT_HELLO_GRACE_MS = 6e4;
|
|
117996
117984
|
var DEFAULT_OFFLINE_MS = 12e4;
|
|
@@ -118087,12 +118075,12 @@ var RunnerReaperService = class {
|
|
|
118087
118075
|
try {
|
|
118088
118076
|
await this.reap(machine, Date.now());
|
|
118089
118077
|
} catch (err) {
|
|
118090
|
-
|
|
118078
|
+
log72.warn(`could not check machine ${machine.id}: ${errorText5(err)}`);
|
|
118091
118079
|
}
|
|
118092
118080
|
}
|
|
118093
118081
|
await this.reapOrphans();
|
|
118094
118082
|
} catch (err) {
|
|
118095
|
-
|
|
118083
|
+
log72.warn(`sweep failed: ${errorText5(err)}`);
|
|
118096
118084
|
} finally {
|
|
118097
118085
|
this.ticking = false;
|
|
118098
118086
|
}
|
|
@@ -118154,7 +118142,7 @@ var RunnerReaperService = class {
|
|
|
118154
118142
|
const deadline = machine.spawnedAt + lifetimeMs + runner.lifetimeGraceSec * 1e3;
|
|
118155
118143
|
if (machine.state === "running") {
|
|
118156
118144
|
this.machines.update(machine.id, { state: "stopping", stoppingSince: now });
|
|
118157
|
-
|
|
118145
|
+
log72.info(`machine ${machine.id} reached its maximum lifetime of ${runner.maxLifetimeSec}s`);
|
|
118158
118146
|
}
|
|
118159
118147
|
const reason = `maximum lifetime of ${runner.maxLifetimeSec}s reached`;
|
|
118160
118148
|
if (!online) {
|
|
@@ -118200,7 +118188,7 @@ var RunnerReaperService = class {
|
|
|
118200
118188
|
return;
|
|
118201
118189
|
}
|
|
118202
118190
|
const lost = this.unstored(machine.workerId);
|
|
118203
|
-
|
|
118191
|
+
log72.error(
|
|
118204
118192
|
`HARD DEADLINE: destroying machine ${machine.id} (${reason}) although worktree(s) ${lost.join(", ") || "of its worker"} were not stored`
|
|
118205
118193
|
);
|
|
118206
118194
|
await this.destroyNow(
|
|
@@ -118227,11 +118215,11 @@ var RunnerReaperService = class {
|
|
|
118227
118215
|
const key2 = `${machine.id}:${text4}`;
|
|
118228
118216
|
if (!this.warned.has(key2)) {
|
|
118229
118217
|
this.warned.add(key2);
|
|
118230
|
-
|
|
118218
|
+
log72.info(`machine ${machine.id}: ${text4}`);
|
|
118231
118219
|
}
|
|
118232
118220
|
}
|
|
118233
118221
|
async destroyNow(machine, reason, opts = {}) {
|
|
118234
|
-
|
|
118222
|
+
log72.info(`destroying machine ${machine.id} of runner ${machine.runnerId}: ${reason}`);
|
|
118235
118223
|
const task = this.runners.destroyMachine(machine.id, reason);
|
|
118236
118224
|
this.pending.add(task);
|
|
118237
118225
|
try {
|
|
@@ -118247,7 +118235,7 @@ var RunnerReaperService = class {
|
|
|
118247
118235
|
tokenService.removeHost(hostId2);
|
|
118248
118236
|
hostRegistry.unregister(hostId2);
|
|
118249
118237
|
} catch (err) {
|
|
118250
|
-
|
|
118238
|
+
log72.warn(`could not remove host ${hostId2}: ${errorText5(err)}`);
|
|
118251
118239
|
}
|
|
118252
118240
|
}
|
|
118253
118241
|
// ---- orphans ---------------------------------------------------------------
|
|
@@ -118266,7 +118254,7 @@ var RunnerReaperService = class {
|
|
|
118266
118254
|
try {
|
|
118267
118255
|
handles = await this.runners.listHandles(runner);
|
|
118268
118256
|
} catch (err) {
|
|
118269
|
-
|
|
118257
|
+
log72.warn(`status of runner ${runner.id} failed: ${errorText5(err)}`);
|
|
118270
118258
|
continue;
|
|
118271
118259
|
}
|
|
118272
118260
|
if (this.runners.hasAttemptInFlight(runner.id)) continue;
|
|
@@ -118278,10 +118266,10 @@ var RunnerReaperService = class {
|
|
|
118278
118266
|
if (nowKnown.has(handle)) continue;
|
|
118279
118267
|
const ok2 = await this.runners.destroyHandle(runner, handle, "no record of this machine");
|
|
118280
118268
|
if (ok2) {
|
|
118281
|
-
|
|
118269
|
+
log72.info(`destroyed orphan ${handle} of runner ${runner.id}`);
|
|
118282
118270
|
this.machines.settleHandle(runner.id, handle, "destroyed by the reaper as an orphan");
|
|
118283
118271
|
} else {
|
|
118284
|
-
|
|
118272
|
+
log72.warn(`could not destroy orphan ${handle} of runner ${runner.id}`);
|
|
118285
118273
|
}
|
|
118286
118274
|
}
|
|
118287
118275
|
}
|
|
@@ -118347,7 +118335,7 @@ init_errors6();
|
|
|
118347
118335
|
init_agent_session_service();
|
|
118348
118336
|
init_chat_service();
|
|
118349
118337
|
init_worktree_service();
|
|
118350
|
-
var
|
|
118338
|
+
var log73 = createLogger("session-service");
|
|
118351
118339
|
var SessionService = class {
|
|
118352
118340
|
/** Lists past sessions for a worktree's chat pane (default chat when
|
|
118353
118341
|
* `chatId` is undefined). */
|
|
@@ -118360,7 +118348,7 @@ var SessionService = class {
|
|
|
118360
118348
|
if (!chatService.get(chatId)) {
|
|
118361
118349
|
chatService.create(input2.worktreeId, { id: chatId, name: "Chat" });
|
|
118362
118350
|
}
|
|
118363
|
-
|
|
118351
|
+
log73.debug({ chatId, worktreeId: input2.worktreeId }, "listing past sessions for chat");
|
|
118364
118352
|
return agentSessionService.listSessions(chatId);
|
|
118365
118353
|
}
|
|
118366
118354
|
};
|
|
@@ -118687,7 +118675,7 @@ init_branch_status_poller();
|
|
|
118687
118675
|
init_client_activity_service();
|
|
118688
118676
|
init_state();
|
|
118689
118677
|
init_tunnel_service();
|
|
118690
|
-
var
|
|
118678
|
+
var log74 = createLogger("trpc.system");
|
|
118691
118679
|
var systemRouter = t.router({
|
|
118692
118680
|
/**
|
|
118693
118681
|
* Combined liveness probe — webserver is always true if this query
|
|
@@ -118695,16 +118683,16 @@ var systemRouter = t.router({
|
|
|
118695
118683
|
* an interval to drive the bottom-bar status pill.
|
|
118696
118684
|
*/
|
|
118697
118685
|
health: publicProcedure.query(() => {
|
|
118698
|
-
|
|
118686
|
+
log74.debug("services.health called");
|
|
118699
118687
|
const tunnel = tunnelService.getStatus();
|
|
118700
|
-
|
|
118688
|
+
log74.debug({ tunnel }, "services.health: tunnel status");
|
|
118701
118689
|
const result = {
|
|
118702
118690
|
webserver: true,
|
|
118703
118691
|
version: package_default.version,
|
|
118704
118692
|
tunnel: tunnel.running,
|
|
118705
118693
|
tunnel_url: tunnel.url
|
|
118706
118694
|
};
|
|
118707
|
-
|
|
118695
|
+
log74.debug({ result }, "services.health result");
|
|
118708
118696
|
return result;
|
|
118709
118697
|
}),
|
|
118710
118698
|
// What this client's UI is doing, so the branch-status poller can slow down. A client names
|
|
@@ -118843,7 +118831,7 @@ init_errors6();
|
|
|
118843
118831
|
init_chat_service();
|
|
118844
118832
|
init_state();
|
|
118845
118833
|
init_task_service();
|
|
118846
|
-
var
|
|
118834
|
+
var log75 = createLogger("tasks-router");
|
|
118847
118835
|
var tasksRouter = t.router({
|
|
118848
118836
|
list: publicProcedure.input(
|
|
118849
118837
|
external_exports2.object({
|
|
@@ -118905,7 +118893,7 @@ var tasksRouter = t.router({
|
|
|
118905
118893
|
if (input2.files && input2.files.length > 0) {
|
|
118906
118894
|
const savedFiles = await saveWorktreeUploads(input2.worktreeId, input2.files);
|
|
118907
118895
|
if (savedFiles.length !== input2.files.length) {
|
|
118908
|
-
|
|
118896
|
+
log75.warn(
|
|
118909
118897
|
{ chatId, submitted: input2.files.length, saved: savedFiles.length },
|
|
118910
118898
|
"tasks.submit: some file uploads were dropped (malformed data URL?)"
|
|
118911
118899
|
);
|
|
@@ -119331,25 +119319,25 @@ var tokensRouter = t.router({
|
|
|
119331
119319
|
init_src();
|
|
119332
119320
|
init_zod();
|
|
119333
119321
|
init_tunnel_service();
|
|
119334
|
-
var
|
|
119322
|
+
var log76 = createLogger("trpc.tunnel");
|
|
119335
119323
|
var tunnelRouter = t.router({
|
|
119336
119324
|
status: publicProcedure.query(() => {
|
|
119337
119325
|
return tunnelService.getStatus();
|
|
119338
119326
|
}),
|
|
119339
119327
|
start: publicProcedure.input(external_exports2.object({}).optional()).mutation(async () => {
|
|
119340
|
-
|
|
119328
|
+
log76.debug("tunnel.start called");
|
|
119341
119329
|
try {
|
|
119342
119330
|
await tunnelService.start();
|
|
119343
119331
|
} catch (err) {
|
|
119344
|
-
|
|
119332
|
+
log76.debug({ err }, "tunnel.start: startTunnel failed");
|
|
119345
119333
|
return { ok: true, url: null };
|
|
119346
119334
|
}
|
|
119347
119335
|
const status = tunnelService.getStatus();
|
|
119348
|
-
|
|
119336
|
+
log76.debug({ status }, "tunnel.start: after startTunnel");
|
|
119349
119337
|
if (status.url) {
|
|
119350
119338
|
return { ok: true, url: status.url };
|
|
119351
119339
|
}
|
|
119352
|
-
|
|
119340
|
+
log76.debug("tunnel.start: no URL available");
|
|
119353
119341
|
return { ok: true, url: null };
|
|
119354
119342
|
}),
|
|
119355
119343
|
stop: publicProcedure.mutation(async () => {
|
|
@@ -119739,8 +119727,8 @@ function verifyWorktreePreviewGrant(worktreeId4, grant, filePath, now = Date.now
|
|
|
119739
119727
|
init_src2();
|
|
119740
119728
|
init_src();
|
|
119741
119729
|
init_resolver();
|
|
119742
|
-
import { join as
|
|
119743
|
-
var
|
|
119730
|
+
import { join as join54, resolve as resolve12, sep as sep8 } from "node:path";
|
|
119731
|
+
var log77 = createLogger("diff-service");
|
|
119744
119732
|
var EMPTY_TREE_ARGS = ["hash-object", "-t", "tree", "/dev/null"];
|
|
119745
119733
|
var DEFAULT_BRANCH_LIMIT = 50;
|
|
119746
119734
|
var STAGING_BRANCH_PRIORITY = [
|
|
@@ -119836,7 +119824,7 @@ function parseFileStatuses(nameStatusOutput) {
|
|
|
119836
119824
|
return fileStatuses;
|
|
119837
119825
|
}
|
|
119838
119826
|
function assertWorktreeRelative(cwd, filePath) {
|
|
119839
|
-
const target = resolve12(
|
|
119827
|
+
const target = resolve12(join54(cwd, filePath));
|
|
119840
119828
|
if (target !== cwd && !target.startsWith(cwd + sep8)) {
|
|
119841
119829
|
throw new Error("Invalid path");
|
|
119842
119830
|
}
|
|
@@ -119851,7 +119839,7 @@ function assertWorktreeRelative(cwd, filePath) {
|
|
|
119851
119839
|
}
|
|
119852
119840
|
async function readUntrackedFileLines(host, cwd, file3) {
|
|
119853
119841
|
try {
|
|
119854
|
-
const content = new TextDecoder().decode(await host.fs.readFile(
|
|
119842
|
+
const content = new TextDecoder().decode(await host.fs.readFile(join54(cwd, file3)));
|
|
119855
119843
|
const lines = content.split("\n");
|
|
119856
119844
|
if (lines.length > 0 && lines[lines.length - 1] === "") {
|
|
119857
119845
|
lines.pop();
|
|
@@ -120087,7 +120075,7 @@ var DiffService = class {
|
|
|
120087
120075
|
);
|
|
120088
120076
|
refs = output2.split("\n").map((line2) => parseBranchRef(line2.trim())).filter((ref) => ref !== null);
|
|
120089
120077
|
} catch (err) {
|
|
120090
|
-
|
|
120078
|
+
log77.error(
|
|
120091
120079
|
`listBranches: for-each-ref failed for ${cwd}: ${err instanceof Error ? err.message : err}`
|
|
120092
120080
|
);
|
|
120093
120081
|
}
|
|
@@ -120198,7 +120186,7 @@ var DiffService = class {
|
|
|
120198
120186
|
const compareBranch = options.compareBranch ?? defaultBranch;
|
|
120199
120187
|
const cwd = worktree.worktree.path;
|
|
120200
120188
|
const execGit2 = gitRunner(worktree.host);
|
|
120201
|
-
const hasGit = await worktree.host.fs.stat(
|
|
120189
|
+
const hasGit = await worktree.host.fs.stat(join54(cwd, ".git")).then(
|
|
120202
120190
|
() => true,
|
|
120203
120191
|
(err) => {
|
|
120204
120192
|
if (err instanceof HostOfflineError || err instanceof HostTimeoutError) throw err;
|
|
@@ -120236,7 +120224,7 @@ var DiffService = class {
|
|
|
120236
120224
|
applyLineCounts(status.staged, parseNumstat(stagedNumstat));
|
|
120237
120225
|
await Promise.all(
|
|
120238
120226
|
status.untracked.map(async (entry) => {
|
|
120239
|
-
const lines = await countUntrackedLines(worktree.host,
|
|
120227
|
+
const lines = await countUntrackedLines(worktree.host, join54(cwd, entry.path));
|
|
120240
120228
|
if (lines !== null) {
|
|
120241
120229
|
entry.additions = lines;
|
|
120242
120230
|
entry.deletions = 0;
|
|
@@ -120393,7 +120381,7 @@ init_src();
|
|
|
120393
120381
|
init_errors6();
|
|
120394
120382
|
init_local_host_policy();
|
|
120395
120383
|
init_worktree_service();
|
|
120396
|
-
var
|
|
120384
|
+
var log78 = createLogger("direct-access");
|
|
120397
120385
|
var DEFAULT_TOKEN_TTL_MS2 = 10 * 6e4;
|
|
120398
120386
|
function tokenTtlMs() {
|
|
120399
120387
|
const ms = Number(process.env.BAND_DIRECT_TOKEN_TTL_MS);
|
|
@@ -120428,7 +120416,7 @@ var DirectAccessService = class {
|
|
|
120428
120416
|
);
|
|
120429
120417
|
return { hostId: hostId2, ...grant };
|
|
120430
120418
|
} catch (err) {
|
|
120431
|
-
|
|
120419
|
+
log78.debug(
|
|
120432
120420
|
{ hostId: hostId2, worktreeId: worktreeId4, message: err instanceof Error ? err.message : String(err) },
|
|
120433
120421
|
"no direct path to the worker"
|
|
120434
120422
|
);
|
|
@@ -120440,7 +120428,7 @@ var directAccessService = new DirectAccessService();
|
|
|
120440
120428
|
|
|
120441
120429
|
// ../../packages/worktree-ops/src/files.ts
|
|
120442
120430
|
init_resolver();
|
|
120443
|
-
import { dirname as dirname16, extname as extname3, join as
|
|
120431
|
+
import { dirname as dirname16, extname as extname3, join as join55, resolve as resolve13, sep as sep9 } from "node:path";
|
|
120444
120432
|
var MAX_FILE_SIZE2 = 1024 * 1024;
|
|
120445
120433
|
var LANG_MAP2 = {
|
|
120446
120434
|
".js": "javascript",
|
|
@@ -120507,7 +120495,7 @@ var FilesService = class {
|
|
|
120507
120495
|
throw new WorktreeNotFoundError(worktreeId4);
|
|
120508
120496
|
}
|
|
120509
120497
|
const root = worktree.worktree.path;
|
|
120510
|
-
const target = resolve13(
|
|
120498
|
+
const target = resolve13(join55(root, relative2));
|
|
120511
120499
|
const insideRoot = target === root || target.startsWith(root + sep9);
|
|
120512
120500
|
if (!insideRoot) {
|
|
120513
120501
|
throw new Error("Invalid path");
|
|
@@ -120688,7 +120676,7 @@ var filesService = new FilesService({
|
|
|
120688
120676
|
|
|
120689
120677
|
// src/server/services/git-graph-service.ts
|
|
120690
120678
|
init_src2();
|
|
120691
|
-
import { createHash as
|
|
120679
|
+
import { createHash as createHash13 } from "node:crypto";
|
|
120692
120680
|
init_errors6();
|
|
120693
120681
|
init_worktree_service();
|
|
120694
120682
|
var FS = "";
|
|
@@ -120760,7 +120748,7 @@ var GitGraphService = class {
|
|
|
120760
120748
|
} catch {
|
|
120761
120749
|
return "";
|
|
120762
120750
|
}
|
|
120763
|
-
return
|
|
120751
|
+
return createHash13("sha1").update(out).digest("hex");
|
|
120764
120752
|
}
|
|
120765
120753
|
/**
|
|
120766
120754
|
* One page of HEAD's history, newest first in topological order, so every
|
|
@@ -122804,7 +122792,7 @@ async function readBody2(req, max3) {
|
|
|
122804
122792
|
// src/server/api/mcp-proxy/stdio.ts
|
|
122805
122793
|
init_src();
|
|
122806
122794
|
init_mcp_stdio_service();
|
|
122807
|
-
var
|
|
122795
|
+
var log79 = createLogger("mcp-proxy-stdio");
|
|
122808
122796
|
var MAX_REQUEST_BYTES = 4 * 1024 * 1024;
|
|
122809
122797
|
var sessionHeader = (req) => {
|
|
122810
122798
|
const value = req.headers["mcp-session-id"];
|
|
@@ -122935,7 +122923,7 @@ data: ${JSON.stringify(message)}
|
|
|
122935
122923
|
if (gone) {
|
|
122936
122924
|
return sendJson3(res, 404, { error: "The stdio MCP server's session ended" });
|
|
122937
122925
|
}
|
|
122938
|
-
|
|
122926
|
+
log79.warn(
|
|
122939
122927
|
{ server: server.name, err: err instanceof Error ? err.name : "unknown" },
|
|
122940
122928
|
"no answer"
|
|
122941
122929
|
);
|
|
@@ -122960,7 +122948,7 @@ data: ${JSON.stringify(message)}
|
|
|
122960
122948
|
}
|
|
122961
122949
|
|
|
122962
122950
|
// src/server/api/mcp-proxy/handler.ts
|
|
122963
|
-
var
|
|
122951
|
+
var log80 = createLogger("mcp-proxy");
|
|
122964
122952
|
var MCP_PROXY_PREFIX = "/mcp-proxy/";
|
|
122965
122953
|
var ROUTE = /^\/mcp-proxy\/([^/]+)\/?$/;
|
|
122966
122954
|
var MAX_REQUEST_BYTES2 = 4 * 1024 * 1024;
|
|
@@ -123122,13 +123110,13 @@ async function handleMcpProxy(req, res) {
|
|
|
123122
123110
|
try {
|
|
123123
123111
|
upstream = await sendUpstream(server, { method, headers, body, signal: abort.signal });
|
|
123124
123112
|
} catch (err) {
|
|
123125
|
-
|
|
123113
|
+
log80.warn({ server: name5, err: errorCode2(err) }, "upstream failed");
|
|
123126
123114
|
auditUnanswered(server, auth2.sessionId, plan, "upstream-unreachable");
|
|
123127
123115
|
return sendJson3(res, 502, { error: "The upstream MCP server did not answer" });
|
|
123128
123116
|
}
|
|
123129
123117
|
if (upstream.status === 401 || upstream.status >= 300 && upstream.status < 400) {
|
|
123130
123118
|
await upstream.body?.cancel().catch(() => void 0);
|
|
123131
|
-
|
|
123119
|
+
log80.warn({ server: name5, status: upstream.status }, "upstream refused the stored credential");
|
|
123132
123120
|
auditUnanswered(server, auth2.sessionId, plan, `upstream-${upstream.status}`);
|
|
123133
123121
|
return sendJson3(res, 502, {
|
|
123134
123122
|
error: upstream.status === 401 ? "The upstream MCP server rejected the stored credential" : "The upstream MCP server redirected, which the proxy does not follow"
|
|
@@ -123196,7 +123184,7 @@ async function handleMcpProxy(req, res) {
|
|
|
123196
123184
|
} catch (err) {
|
|
123197
123185
|
auditUnanswered(server, auth2.sessionId, plan, "stream-failed");
|
|
123198
123186
|
if (!abort.signal.aborted) {
|
|
123199
|
-
|
|
123187
|
+
log80.warn(
|
|
123200
123188
|
{ server: name5, err: errorCode2(err) },
|
|
123201
123189
|
err instanceof SseEventTooLargeError ? "event too large to inspect" : "proxy stream failed"
|
|
123202
123190
|
);
|
|
@@ -123231,7 +123219,7 @@ function getScalarHtml(specUrl) {
|
|
|
123231
123219
|
// src/server/api/pairing/handler.ts
|
|
123232
123220
|
init_src();
|
|
123233
123221
|
init_token_service();
|
|
123234
|
-
var
|
|
123222
|
+
var log81 = createLogger("pairing");
|
|
123235
123223
|
var PAIR_EXCHANGE_PATH = "/api/pair/exchange";
|
|
123236
123224
|
var MAX_BODY_BYTES2 = 4096;
|
|
123237
123225
|
var PAIR_REFUSED_MESSAGE = "This link was already used or has expired. Ask for a new one in Settings > Devices.";
|
|
@@ -123323,7 +123311,7 @@ async function handlePairExchange(req, res) {
|
|
|
123323
123311
|
send3(200, out, { "Set-Cookie": buildCookieHeader(out.token, isSecure(req)) });
|
|
123324
123312
|
} catch (err) {
|
|
123325
123313
|
if (!(err instanceof PairingExchangeError)) throw err;
|
|
123326
|
-
|
|
123314
|
+
log81.debug(`pairing exchange refused: ${err.reason}`);
|
|
123327
123315
|
send3(401, { error: PAIR_REFUSED_MESSAGE });
|
|
123328
123316
|
}
|
|
123329
123317
|
}
|
|
@@ -123331,7 +123319,7 @@ async function handlePairExchange(req, res) {
|
|
|
123331
123319
|
// src/server/api/provisioning/handler.ts
|
|
123332
123320
|
init_src();
|
|
123333
123321
|
import { pipeline } from "node:stream";
|
|
123334
|
-
var
|
|
123322
|
+
var log82 = createLogger("provisioning");
|
|
123335
123323
|
var PROVISION_PREFIX = "/api/provision/";
|
|
123336
123324
|
var MAX_EXCHANGE_BODY_BYTES2 = 4096;
|
|
123337
123325
|
var MAX_LOG_BODY_BYTES = 128 * 1024;
|
|
@@ -123388,7 +123376,7 @@ async function handleProvision(req, res) {
|
|
|
123388
123376
|
send3(200, provisioningService.exchange(code2), "text/plain; charset=utf-8");
|
|
123389
123377
|
} catch (err) {
|
|
123390
123378
|
if (!(err instanceof ProvisionExchangeError)) throw err;
|
|
123391
|
-
|
|
123379
|
+
log82.debug(`provisioning exchange refused: ${err.reason}`);
|
|
123392
123380
|
refused();
|
|
123393
123381
|
}
|
|
123394
123382
|
return;
|
|
@@ -123524,7 +123512,7 @@ var OutputFlow = class {
|
|
|
123524
123512
|
};
|
|
123525
123513
|
|
|
123526
123514
|
// ../../packages/worktree-ops/src/terminal-socket.ts
|
|
123527
|
-
var
|
|
123515
|
+
var log83 = createLogger("terminal-ws");
|
|
123528
123516
|
var MAX_CLOSE_REASON_BYTES = 123;
|
|
123529
123517
|
var HEARTBEAT_INTERVAL_MS2 = 3e4;
|
|
123530
123518
|
function clampCloseReason(reason) {
|
|
@@ -123592,7 +123580,7 @@ function createInbox(ws) {
|
|
|
123592
123580
|
};
|
|
123593
123581
|
}
|
|
123594
123582
|
function attachSession(backend, ws, inbox, terminalId, worktreeId4, isNew, pendingMessage) {
|
|
123595
|
-
|
|
123583
|
+
log83.debug(
|
|
123596
123584
|
"Terminal %s: %s (worktree %s)",
|
|
123597
123585
|
isNew ? "connected" : "reconnected",
|
|
123598
123586
|
terminalId,
|
|
@@ -123612,7 +123600,7 @@ function attachSession(backend, ws, inbox, terminalId, worktreeId4, isNew, pendi
|
|
|
123612
123600
|
});
|
|
123613
123601
|
const unsubscribeExit = backend.onExit(terminalId, (event) => {
|
|
123614
123602
|
unsubscribeTitle();
|
|
123615
|
-
|
|
123603
|
+
log83.debug("PTY exited with code %d for terminal %s", event.exitCode, terminalId);
|
|
123616
123604
|
if (ws.readyState === ws.OPEN) {
|
|
123617
123605
|
ws.close(1e3, "Terminal exited");
|
|
123618
123606
|
}
|
|
@@ -123640,7 +123628,7 @@ function attachSession(backend, ws, inbox, terminalId, worktreeId4, isNew, pendi
|
|
|
123640
123628
|
try {
|
|
123641
123629
|
attached = await backend.attach(terminalId, dims);
|
|
123642
123630
|
} catch (err) {
|
|
123643
|
-
|
|
123631
|
+
log83.error("Failed to attach terminal %s: %s", terminalId, err);
|
|
123644
123632
|
safeClose(ws, 1011, "Terminal attach failed");
|
|
123645
123633
|
return;
|
|
123646
123634
|
}
|
|
@@ -123682,7 +123670,7 @@ function attachSession(backend, ws, inbox, terminalId, worktreeId4, isNew, pendi
|
|
|
123682
123670
|
const cols = Number.isFinite(parsed.cols) && parsed.cols > 0 ? parsed.cols : void 0;
|
|
123683
123671
|
const rows = Number.isFinite(parsed.rows) && parsed.rows > 0 ? parsed.rows : void 0;
|
|
123684
123672
|
void startReplay(cols, rows, parsed.flow === true).catch((err) => {
|
|
123685
|
-
|
|
123673
|
+
log83.error("Failed to replay terminal %s: %s", terminalId, err);
|
|
123686
123674
|
});
|
|
123687
123675
|
return;
|
|
123688
123676
|
}
|
|
@@ -123702,7 +123690,7 @@ function attachSession(backend, ws, inbox, terminalId, worktreeId4, isNew, pendi
|
|
|
123702
123690
|
flow?.dispose();
|
|
123703
123691
|
attachment?.detach();
|
|
123704
123692
|
unsubscribeExit();
|
|
123705
|
-
|
|
123693
|
+
log83.debug("Terminal disconnected: %s (PTY kept alive)", terminalId);
|
|
123706
123694
|
});
|
|
123707
123695
|
if (pendingMessage) {
|
|
123708
123696
|
processMessage(pendingMessage);
|
|
@@ -123725,7 +123713,7 @@ function handleMessage(backend, ws, terminalId, message) {
|
|
|
123725
123713
|
}
|
|
123726
123714
|
if (parsed.type === "close") {
|
|
123727
123715
|
void backend.kill(terminalId).catch((err) => {
|
|
123728
|
-
|
|
123716
|
+
log83.error("Failed to kill terminal %s: %s", terminalId, err);
|
|
123729
123717
|
});
|
|
123730
123718
|
ws.close(1e3, "Terminal closed by client");
|
|
123731
123719
|
return;
|
|
@@ -123741,7 +123729,7 @@ function handleMessage(backend, ws, terminalId, message) {
|
|
|
123741
123729
|
|
|
123742
123730
|
// src/server/api/terminals/ws.ts
|
|
123743
123731
|
init_terminal_service();
|
|
123744
|
-
var
|
|
123732
|
+
var log84 = createLogger("terminal-ws");
|
|
123745
123733
|
async function handleTerminalConnection(ws, req) {
|
|
123746
123734
|
if (!req.url) {
|
|
123747
123735
|
safeClose(ws, 4e3, "Missing request URL");
|
|
@@ -123760,7 +123748,7 @@ async function handleTerminalConnection(ws, req) {
|
|
|
123760
123748
|
existing = await terminalService.info(terminalId) !== null;
|
|
123761
123749
|
} catch (err) {
|
|
123762
123750
|
const msg = err instanceof Error ? err.message : String(err);
|
|
123763
|
-
|
|
123751
|
+
log84.error("Failed to look up terminal %s: %s", terminalId, msg);
|
|
123764
123752
|
safeClose(ws, 1011, msg);
|
|
123765
123753
|
return;
|
|
123766
123754
|
}
|
|
@@ -123808,7 +123796,7 @@ async function handleTerminalConnection(ws, req) {
|
|
|
123808
123796
|
await terminalService.spawn(worktreeId4, terminalId, spawnOpts);
|
|
123809
123797
|
} catch (err) {
|
|
123810
123798
|
const msg = err instanceof Error ? err.message : String(err);
|
|
123811
|
-
|
|
123799
|
+
log84.error("Failed to spawn terminal %s for worktree %s: %s", terminalId, worktreeId4, msg);
|
|
123812
123800
|
safeClose(ws, 4001, msg);
|
|
123813
123801
|
return;
|
|
123814
123802
|
}
|
|
@@ -123908,14 +123896,14 @@ async function handleVoiceTranscribe(req, res) {
|
|
|
123908
123896
|
|
|
123909
123897
|
// src/server/api/web-app-manifest.ts
|
|
123910
123898
|
import { createReadStream as createReadStream5, statSync as statSync15 } from "node:fs";
|
|
123911
|
-
import { join as
|
|
123899
|
+
import { join as join56 } from "node:path";
|
|
123912
123900
|
var WEB_APP_MANIFEST_PATH = "/manifest.webmanifest";
|
|
123913
123901
|
var ICON_FILES = ["band-192.png", "band-512.png", "apple-touch-icon.png"];
|
|
123914
123902
|
function handleWebAppManifest(req, res, publicDir) {
|
|
123915
123903
|
if (req.method !== "GET" && req.method !== "HEAD") return false;
|
|
123916
123904
|
const pathname = req.url?.split("?")[0];
|
|
123917
123905
|
if (pathname === WEB_APP_MANIFEST_PATH) {
|
|
123918
|
-
sendFile(req, res,
|
|
123906
|
+
sendFile(req, res, join56(publicDir, "manifest.webmanifest"), {
|
|
123919
123907
|
"Content-Type": "application/manifest+json",
|
|
123920
123908
|
"Cache-Control": "no-cache"
|
|
123921
123909
|
});
|
|
@@ -123923,7 +123911,7 @@ function handleWebAppManifest(req, res, publicDir) {
|
|
|
123923
123911
|
}
|
|
123924
123912
|
const icon = ICON_FILES.find((name5) => pathname === `/icons/${name5}`);
|
|
123925
123913
|
if (!icon) return false;
|
|
123926
|
-
sendFile(req, res,
|
|
123914
|
+
sendFile(req, res, join56(publicDir, "icons", icon), {
|
|
123927
123915
|
"Content-Type": "image/png",
|
|
123928
123916
|
"Cache-Control": "public, max-age=86400"
|
|
123929
123917
|
});
|
|
@@ -123947,7 +123935,7 @@ init_src();
|
|
|
123947
123935
|
init_wrapper();
|
|
123948
123936
|
init_browser_lookup();
|
|
123949
123937
|
init_remote_cdp();
|
|
123950
|
-
var
|
|
123938
|
+
var log85 = createLogger("cdp-proxy");
|
|
123951
123939
|
async function handleCdpConnection(ws, req) {
|
|
123952
123940
|
const url3 = new URL(req.url ?? "", `http://${req.headers.host}`);
|
|
123953
123941
|
const bandTabId = url3.searchParams.get("bandTabId");
|
|
@@ -123990,17 +123978,17 @@ async function handleCdpConnection(ws, req) {
|
|
|
123990
123978
|
cdpTargetId = await ensureCdpTargetId(bandTabId);
|
|
123991
123979
|
} catch (err) {
|
|
123992
123980
|
const message = err instanceof Error ? err.message : String(err);
|
|
123993
|
-
|
|
123981
|
+
log85.debug("ensureCdpTargetId failed for %s: %s", bandTabId, message);
|
|
123994
123982
|
if (ws.readyState === ws.OPEN) {
|
|
123995
123983
|
ws.close(4001, message.slice(0, 123));
|
|
123996
123984
|
}
|
|
123997
123985
|
return;
|
|
123998
123986
|
}
|
|
123999
123987
|
const upstreamUrl = `ws://${DESKTOP_CDP_HOST}:${DESKTOP_CDP_PORT}/devtools/page/${encodeURIComponent(cdpTargetId)}`;
|
|
124000
|
-
|
|
123988
|
+
log85.info("CDP proxy connecting bandTabId=%s upstream=%s", bandTabId, upstreamUrl);
|
|
124001
123989
|
upstream = new wrapper_default(upstreamUrl);
|
|
124002
123990
|
upstream.on("open", () => {
|
|
124003
|
-
|
|
123991
|
+
log85.info("CDP upstream open bandTabId=%s pending=%d", bandTabId, pending2.length);
|
|
124004
123992
|
for (const msg of pending2) {
|
|
124005
123993
|
upstream?.send(msg);
|
|
124006
123994
|
}
|
|
@@ -124012,20 +124000,20 @@ async function handleCdpConnection(ws, req) {
|
|
|
124012
124000
|
}
|
|
124013
124001
|
});
|
|
124014
124002
|
upstream.on("error", (err) => {
|
|
124015
|
-
|
|
124003
|
+
log85.warn("CDP upstream error bandTabId=%s: %s", bandTabId, err.message);
|
|
124016
124004
|
markTargetDestroyed(bandTabId);
|
|
124017
124005
|
if (ws.readyState === ws.OPEN) {
|
|
124018
124006
|
ws.close(4001, `Desktop CDP error: ${err.message}`.slice(0, 123));
|
|
124019
124007
|
}
|
|
124020
124008
|
});
|
|
124021
124009
|
upstream.on("close", (code) => {
|
|
124022
|
-
|
|
124010
|
+
log85.info("CDP upstream closed bandTabId=%s code=%d", bandTabId, code);
|
|
124023
124011
|
if (ws.readyState === ws.OPEN) {
|
|
124024
124012
|
ws.close(1e3, "Upstream closed");
|
|
124025
124013
|
}
|
|
124026
124014
|
});
|
|
124027
124015
|
ws.on("close", () => {
|
|
124028
|
-
|
|
124016
|
+
log85.debug("CDP client closed bandTabId=%s", bandTabId);
|
|
124029
124017
|
if (upstream && (upstream.readyState === wrapper_default.OPEN || upstream.readyState === wrapper_default.CONNECTING)) {
|
|
124030
124018
|
try {
|
|
124031
124019
|
upstream.close();
|
|
@@ -124034,7 +124022,7 @@ async function handleCdpConnection(ws, req) {
|
|
|
124034
124022
|
}
|
|
124035
124023
|
});
|
|
124036
124024
|
ws.on("error", (err) => {
|
|
124037
|
-
|
|
124025
|
+
log85.debug("CDP client error bandTabId=%s: %s", bandTabId, err.message);
|
|
124038
124026
|
try {
|
|
124039
124027
|
upstream?.close();
|
|
124040
124028
|
} catch {
|
|
@@ -124064,7 +124052,7 @@ async function bridgeRemote(ws, worktreeId4) {
|
|
|
124064
124052
|
cdp = await openRemoteCdp(worktreeId4);
|
|
124065
124053
|
} catch (err) {
|
|
124066
124054
|
const message = err instanceof Error ? err.message : String(err);
|
|
124067
|
-
|
|
124055
|
+
log85.warn("remote CDP failed for worktree %s: %s", worktreeId4, message);
|
|
124068
124056
|
if (ws.readyState === ws.OPEN)
|
|
124069
124057
|
ws.close(4001, closeReason(`Remote browser unavailable: ${message}`));
|
|
124070
124058
|
return true;
|
|
@@ -124088,7 +124076,7 @@ async function bridgeRemote(ws, worktreeId4) {
|
|
|
124088
124076
|
if (ws.readyState === ws.OPEN) ws.send(message);
|
|
124089
124077
|
}
|
|
124090
124078
|
} catch (err) {
|
|
124091
|
-
|
|
124079
|
+
log85.debug("remote CDP stream ended for worktree %s: %s", worktreeId4, String(err));
|
|
124092
124080
|
}
|
|
124093
124081
|
if (ws.readyState === ws.OPEN) ws.close(1e3, "Upstream closed");
|
|
124094
124082
|
})();
|
|
@@ -124098,7 +124086,7 @@ async function bridgeRemote(ws, worktreeId4) {
|
|
|
124098
124086
|
// src/server/infra/browser-host/cdp-targets.ts
|
|
124099
124087
|
init_src();
|
|
124100
124088
|
init_wrapper();
|
|
124101
|
-
var
|
|
124089
|
+
var log86 = createLogger("cdp-targets");
|
|
124102
124090
|
var CdpUnreachableError = class extends Error {
|
|
124103
124091
|
constructor(message) {
|
|
124104
124092
|
super(message);
|
|
@@ -124154,7 +124142,7 @@ async function captureSnapshot(bandTabId) {
|
|
|
124154
124142
|
});
|
|
124155
124143
|
ws.on("error", (err) => {
|
|
124156
124144
|
clearTimeout(timeout);
|
|
124157
|
-
|
|
124145
|
+
log86.debug("captureSnapshot ws error for tab %s: %s", bandTabId, err.message);
|
|
124158
124146
|
markTargetDestroyed(bandTabId);
|
|
124159
124147
|
settle2(new CdpUnreachableError(err.message));
|
|
124160
124148
|
});
|
|
@@ -124281,7 +124269,7 @@ var RfbClientFilter = class {
|
|
|
124281
124269
|
};
|
|
124282
124270
|
|
|
124283
124271
|
// src/server/infra/host/desktop-proxy.ts
|
|
124284
|
-
var
|
|
124272
|
+
var log87 = createLogger("desktop-proxy");
|
|
124285
124273
|
var DESKTOP_PATH = /^\/api\/hosts\/([^/]+)\/desktop$/;
|
|
124286
124274
|
function desktopHostId(pathname) {
|
|
124287
124275
|
const match = DESKTOP_PATH.exec(pathname);
|
|
@@ -124330,7 +124318,7 @@ async function handleDesktopConnection(ws, req, hostId2) {
|
|
|
124330
124318
|
);
|
|
124331
124319
|
if (enabled !== null) {
|
|
124332
124320
|
filter.viewOnly = !enabled;
|
|
124333
|
-
|
|
124321
|
+
log87.debug("desktop of host %s is now %s", hostId2, enabled ? "controlled" : "view-only");
|
|
124334
124322
|
}
|
|
124335
124323
|
return;
|
|
124336
124324
|
}
|
|
@@ -124365,7 +124353,7 @@ async function handleDesktopConnection(ws, req, hostId2) {
|
|
|
124365
124353
|
opened = true;
|
|
124366
124354
|
} catch (err) {
|
|
124367
124355
|
const message = err instanceof Error ? err.message : String(err);
|
|
124368
|
-
|
|
124356
|
+
log87.warn("desktop of host %s is unavailable: %s", hostId2, message);
|
|
124369
124357
|
release();
|
|
124370
124358
|
ws.close(4001, message.slice(0, 120));
|
|
124371
124359
|
return;
|
|
@@ -124375,7 +124363,7 @@ async function handleDesktopConnection(ws, req, hostId2) {
|
|
|
124375
124363
|
release();
|
|
124376
124364
|
return;
|
|
124377
124365
|
}
|
|
124378
|
-
|
|
124366
|
+
log87.debug("desktop viewer connected: %s (%s)", hostId2, req.socket.remoteAddress ?? "unknown");
|
|
124379
124367
|
for (const chunk of pending2.splice(0)) desktop.write(chunk);
|
|
124380
124368
|
try {
|
|
124381
124369
|
for await (const bytes of desktop.output) {
|
|
@@ -124383,7 +124371,7 @@ async function handleDesktopConnection(ws, req, hostId2) {
|
|
|
124383
124371
|
await new Promise((resolve15) => ws.send(bytes, { binary: true }, () => resolve15()));
|
|
124384
124372
|
}
|
|
124385
124373
|
} catch (err) {
|
|
124386
|
-
|
|
124374
|
+
log87.warn("desktop stream of host %s failed: %s", hostId2, err.message);
|
|
124387
124375
|
} finally {
|
|
124388
124376
|
if (opened) {
|
|
124389
124377
|
desktop.close();
|
|
@@ -124401,7 +124389,7 @@ init_src();
|
|
|
124401
124389
|
init_worktrees();
|
|
124402
124390
|
init_registry();
|
|
124403
124391
|
var worktreeQueries2 = new WorktreeQueries();
|
|
124404
|
-
var
|
|
124392
|
+
var log88 = createLogger("lsp-proxy");
|
|
124405
124393
|
function frameMessage(json3) {
|
|
124406
124394
|
const body = Buffer.from(json3, "utf-8");
|
|
124407
124395
|
const header = `Content-Length: ${body.byteLength}\r
|
|
@@ -124419,7 +124407,7 @@ function createFrameParser(onMessage) {
|
|
|
124419
124407
|
const headerStr = buffer.subarray(0, separatorIdx).toString("ascii");
|
|
124420
124408
|
const match = headerStr.match(/Content-Length:\s*(\d+)/i);
|
|
124421
124409
|
if (!match) {
|
|
124422
|
-
|
|
124410
|
+
log88.warn("Malformed LSP header: %s", headerStr);
|
|
124423
124411
|
buffer = buffer.subarray(separatorIdx + 4);
|
|
124424
124412
|
continue;
|
|
124425
124413
|
}
|
|
@@ -124464,7 +124452,7 @@ async function handleLspConnection(ws, req) {
|
|
|
124464
124452
|
connection = await hostRegistry.hostFor(worktreeId4).lsp.connect({ worktreeId: worktreeId4, lang, root: worktree.worktreePath });
|
|
124465
124453
|
} catch (err) {
|
|
124466
124454
|
const message = err instanceof Error ? err.message : String(err);
|
|
124467
|
-
|
|
124455
|
+
log88.error("Failed to spawn %s language server for worktree %s: %s", lang, worktreeId4, message);
|
|
124468
124456
|
ws.close(4001, message);
|
|
124469
124457
|
return;
|
|
124470
124458
|
}
|
|
@@ -124472,7 +124460,7 @@ async function handleLspConnection(ws, req) {
|
|
|
124472
124460
|
connection.close();
|
|
124473
124461
|
return;
|
|
124474
124462
|
}
|
|
124475
|
-
|
|
124463
|
+
log88.debug("LSP client connected: %s/%s", worktreeId4, lang);
|
|
124476
124464
|
const pendingRequests = /* @__PURE__ */ new Map();
|
|
124477
124465
|
const openDocuments = /* @__PURE__ */ new Set();
|
|
124478
124466
|
const serverId = `${worktreeId4}:${lang}`;
|
|
@@ -124508,7 +124496,7 @@ async function handleLspConnection(ws, req) {
|
|
|
124508
124496
|
const retriedIds = /* @__PURE__ */ new Set();
|
|
124509
124497
|
const RETRY_DELAY_MS = 2e3;
|
|
124510
124498
|
const parseFrame = createFrameParser((json3) => {
|
|
124511
|
-
|
|
124499
|
+
log88.debug(
|
|
124512
124500
|
"LSP stdout [%s/%s]: %s",
|
|
124513
124501
|
worktreeId4,
|
|
124514
124502
|
lang,
|
|
@@ -124520,7 +124508,7 @@ async function handleLspConnection(ws, req) {
|
|
|
124520
124508
|
const originalRequest = pendingRequests.get(msg.id);
|
|
124521
124509
|
retriedIds.add(msg.id);
|
|
124522
124510
|
pendingRequests.delete(msg.id);
|
|
124523
|
-
|
|
124511
|
+
log88.debug(
|
|
124524
124512
|
"LSP retrying request %d after 'No Project' error [%s/%s]",
|
|
124525
124513
|
msg.id,
|
|
124526
124514
|
worktreeId4,
|
|
@@ -124551,16 +124539,16 @@ async function handleLspConnection(ws, req) {
|
|
|
124551
124539
|
for await (const chunk of connection.output)
|
|
124552
124540
|
parseFrame(Buffer.from(chunk.buffer, chunk.byteOffset, chunk.byteLength));
|
|
124553
124541
|
} catch (err) {
|
|
124554
|
-
|
|
124542
|
+
log88.warn("LSP output stream failed [%s/%s]: %s", worktreeId4, lang, String(err));
|
|
124555
124543
|
}
|
|
124556
124544
|
release();
|
|
124557
124545
|
if (ws.readyState === ws.OPEN) {
|
|
124558
|
-
|
|
124546
|
+
log88.debug("LSP server exited, closing WebSocket");
|
|
124559
124547
|
ws.close(1e3, "Language server exited");
|
|
124560
124548
|
}
|
|
124561
124549
|
})();
|
|
124562
124550
|
function forwardToStdin(json3) {
|
|
124563
|
-
|
|
124551
|
+
log88.debug(
|
|
124564
124552
|
"LSP stdin [%s/%s]: %s",
|
|
124565
124553
|
worktreeId4,
|
|
124566
124554
|
lang,
|
|
@@ -124592,7 +124580,7 @@ async function handleLspConnection(ws, req) {
|
|
|
124592
124580
|
ws.on("close", () => {
|
|
124593
124581
|
release();
|
|
124594
124582
|
connection.close();
|
|
124595
|
-
|
|
124583
|
+
log88.debug("LSP client disconnected: %s/%s (server kept alive)", worktreeId4, lang);
|
|
124596
124584
|
});
|
|
124597
124585
|
}
|
|
124598
124586
|
|
|
@@ -124601,8 +124589,8 @@ init_webhook();
|
|
|
124601
124589
|
|
|
124602
124590
|
// src/server/services/_utils/hosted-file.ts
|
|
124603
124591
|
init_registry();
|
|
124604
|
-
import { basename as basename6, join as
|
|
124605
|
-
async function openHostedFile(kind, worktreeId4, rawName) {
|
|
124592
|
+
import { basename as basename6, dirname as dirname17, join as join57 } from "node:path";
|
|
124593
|
+
async function openHostedFile(kind, worktreeId4, rawName, chatId) {
|
|
124606
124594
|
const host = hostRegistry.hostFor(worktreeId4);
|
|
124607
124595
|
if (host.id === hostRegistry.local.id) return null;
|
|
124608
124596
|
let name5;
|
|
@@ -124615,7 +124603,9 @@ async function openHostedFile(kind, worktreeId4, rawName) {
|
|
|
124615
124603
|
try {
|
|
124616
124604
|
const dirs = (await host.info()).dirs;
|
|
124617
124605
|
if (!dirs) return null;
|
|
124618
|
-
const path2 =
|
|
124606
|
+
const path2 = chatId ? join57(dirs[kind], worktreeId4, chatId, name5) : join57(dirs[kind], worktreeId4, name5);
|
|
124607
|
+
const dir = await host.fs.realpath(dirname17(path2));
|
|
124608
|
+
if (!(await host.fs.realpath(path2)).startsWith(`${dir}/`)) return null;
|
|
124619
124609
|
const stat7 = await host.fs.stat(path2, { followSymlinks: true });
|
|
124620
124610
|
if (stat7.kind !== "file") return null;
|
|
124621
124611
|
return { size: stat7.size, stream: host.fs.readStream(path2) };
|
|
@@ -132736,6 +132726,7 @@ async function listenWithFallback(server, startPort, attempts = 20) {
|
|
|
132736
132726
|
}
|
|
132737
132727
|
|
|
132738
132728
|
// start-server.ts
|
|
132729
|
+
init_shared_dir();
|
|
132739
132730
|
init_agent_session_registry_service();
|
|
132740
132731
|
init_branch_status_poller();
|
|
132741
132732
|
init_browser_service();
|
|
@@ -132754,15 +132745,15 @@ init_src();
|
|
|
132754
132745
|
init_registry();
|
|
132755
132746
|
async function installSkills2(opts = {}) {
|
|
132756
132747
|
const result = await hostRegistry.local.agentEnv.installSkills({ home: opts.home });
|
|
132757
|
-
const
|
|
132758
|
-
if (
|
|
132759
|
-
for (const warning of result.warnings)
|
|
132760
|
-
for (const path2 of result.written)
|
|
132748
|
+
const log90 = opts.log;
|
|
132749
|
+
if (log90) {
|
|
132750
|
+
for (const warning of result.warnings) log90.warn(warning);
|
|
132751
|
+
for (const path2 of result.written) log90.info("Installed skill at %s", path2);
|
|
132761
132752
|
for (const path2 of result.updated) {
|
|
132762
|
-
|
|
132753
|
+
log90.info("Updated skill at %s (content differed \u2014 shipped version reinstalled)", path2);
|
|
132763
132754
|
}
|
|
132764
132755
|
for (const conflict of result.conflicts) {
|
|
132765
|
-
|
|
132756
|
+
log90.warn("Skill symlink conflict \u2014 %s (left as-is; remove it manually to re-link)", conflict);
|
|
132766
132757
|
}
|
|
132767
132758
|
}
|
|
132768
132759
|
return result;
|
|
@@ -132775,7 +132766,7 @@ init_state();
|
|
|
132775
132766
|
init_sync_service();
|
|
132776
132767
|
init_worktree_group_service();
|
|
132777
132768
|
init_worktree_service();
|
|
132778
|
-
var
|
|
132769
|
+
var log89 = createLogger("setup");
|
|
132779
132770
|
async function runFirstTimeSetup() {
|
|
132780
132771
|
forgetLocalWorktrees();
|
|
132781
132772
|
convertLegacyLabels();
|
|
@@ -132788,7 +132779,7 @@ async function runFirstTimeSetup() {
|
|
|
132788
132779
|
]);
|
|
132789
132780
|
for (const r of results) {
|
|
132790
132781
|
if (r.status === "rejected") {
|
|
132791
|
-
|
|
132782
|
+
log89.warn(
|
|
132792
132783
|
"Setup step failed: %s",
|
|
132793
132784
|
r.reason instanceof Error ? r.reason.message : String(r.reason)
|
|
132794
132785
|
);
|
|
@@ -132802,7 +132793,7 @@ async function refreshAgentModelsInBackground() {
|
|
|
132802
132793
|
const ok2 = results.filter((r) => !r.error).length;
|
|
132803
132794
|
const failed = results.length - ok2;
|
|
132804
132795
|
if (results.length > 0) {
|
|
132805
|
-
|
|
132796
|
+
log89.info(
|
|
132806
132797
|
"Background model refresh: %d/%d agents updated (%d failed)",
|
|
132807
132798
|
ok2,
|
|
132808
132799
|
results.length,
|
|
@@ -132810,7 +132801,7 @@ async function refreshAgentModelsInBackground() {
|
|
|
132810
132801
|
);
|
|
132811
132802
|
}
|
|
132812
132803
|
} catch (err) {
|
|
132813
|
-
|
|
132804
|
+
log89.warn(
|
|
132814
132805
|
"Background model refresh failed: %s",
|
|
132815
132806
|
err instanceof Error ? err.message : String(err)
|
|
132816
132807
|
);
|
|
@@ -132825,7 +132816,7 @@ async function ensureRepoRemotes() {
|
|
|
132825
132816
|
try {
|
|
132826
132817
|
await repoService.backfillRemotes();
|
|
132827
132818
|
} catch (err) {
|
|
132828
|
-
|
|
132819
|
+
log89.warn(
|
|
132829
132820
|
"Failed to record repo remotes at boot: %s",
|
|
132830
132821
|
err instanceof Error ? err.message : String(err)
|
|
132831
132822
|
);
|
|
@@ -132835,7 +132826,7 @@ function migrateRepoCronjobs() {
|
|
|
132835
132826
|
try {
|
|
132836
132827
|
cronjobService.migrateRepoJobs();
|
|
132837
132828
|
} catch (err) {
|
|
132838
|
-
|
|
132829
|
+
log89.warn(
|
|
132839
132830
|
"Failed to move repo-scoped cronjobs to worktrees at boot: %s",
|
|
132840
132831
|
err instanceof Error ? err.message : String(err)
|
|
132841
132832
|
);
|
|
@@ -132845,7 +132836,7 @@ function convertLegacyLabels() {
|
|
|
132845
132836
|
try {
|
|
132846
132837
|
worktreeGroupService.convertLegacyLabels();
|
|
132847
132838
|
} catch (err) {
|
|
132848
|
-
|
|
132839
|
+
log89.warn(
|
|
132849
132840
|
"Failed to convert repo labels to groups at boot: %s",
|
|
132850
132841
|
err instanceof Error ? err.message : String(err)
|
|
132851
132842
|
);
|
|
@@ -132855,7 +132846,7 @@ function forgetLocalWorktrees() {
|
|
|
132855
132846
|
try {
|
|
132856
132847
|
worktreeService.forgetLocalWorktrees();
|
|
132857
132848
|
} catch (err) {
|
|
132858
|
-
|
|
132849
|
+
log89.warn(
|
|
132859
132850
|
"Failed to forget local worktrees at boot: %s",
|
|
132860
132851
|
err instanceof Error ? err.message : String(err)
|
|
132861
132852
|
);
|
|
@@ -132865,7 +132856,7 @@ async function ensureRepoStateInSync() {
|
|
|
132865
132856
|
try {
|
|
132866
132857
|
await syncService.syncWorktrees();
|
|
132867
132858
|
} catch (err) {
|
|
132868
|
-
|
|
132859
|
+
log89.warn(
|
|
132869
132860
|
"Failed to sync repo state at boot: %s",
|
|
132870
132861
|
err instanceof Error ? err.message : String(err)
|
|
132871
132862
|
);
|
|
@@ -132876,22 +132867,22 @@ async function ensureCliInstalled() {
|
|
|
132876
132867
|
try {
|
|
132877
132868
|
cliStatus = await checkCli();
|
|
132878
132869
|
} catch (err) {
|
|
132879
|
-
|
|
132870
|
+
log89.warn("Could not check CLI status: %s", err instanceof Error ? err.message : String(err));
|
|
132880
132871
|
return;
|
|
132881
132872
|
}
|
|
132882
132873
|
if (cliStatus === "Installed") {
|
|
132883
132874
|
return;
|
|
132884
132875
|
}
|
|
132885
132876
|
if (cliStatus !== "NotInstalled") {
|
|
132886
|
-
|
|
132877
|
+
log89.warn("CLI not auto-installed (status: %s)", cliStatus);
|
|
132887
132878
|
return;
|
|
132888
132879
|
}
|
|
132889
|
-
|
|
132880
|
+
log89.info("Installing band CLI...");
|
|
132890
132881
|
try {
|
|
132891
132882
|
await installCli();
|
|
132892
|
-
|
|
132883
|
+
log89.info("CLI installed to %s", SYMLINK_PATH);
|
|
132893
132884
|
} catch (err) {
|
|
132894
|
-
|
|
132885
|
+
log89.warn("CLI installation failed: %s", err instanceof Error ? err.message : String(err));
|
|
132895
132886
|
}
|
|
132896
132887
|
}
|
|
132897
132888
|
async function ensureDefaultCodingAgents() {
|
|
@@ -132900,17 +132891,17 @@ async function ensureDefaultCodingAgents() {
|
|
|
132900
132891
|
if (Array.isArray(existing) && existing.length > 0) {
|
|
132901
132892
|
return;
|
|
132902
132893
|
}
|
|
132903
|
-
|
|
132894
|
+
log89.info("Detecting installed coding agents...");
|
|
132904
132895
|
const detected = [];
|
|
132905
132896
|
for (const check3 of AGENT_CHECKS) {
|
|
132906
132897
|
const path2 = await systemService.whichBinary(check3.binary);
|
|
132907
132898
|
if (path2) {
|
|
132908
|
-
|
|
132899
|
+
log89.info("Detected coding agent: %s (%s)", check3.id, path2);
|
|
132909
132900
|
detected.push({ id: check3.id, type: check3.type, label: check3.label });
|
|
132910
132901
|
}
|
|
132911
132902
|
}
|
|
132912
132903
|
if (detected.length === 0) {
|
|
132913
|
-
|
|
132904
|
+
log89.info("No coding agent CLIs detected on PATH");
|
|
132914
132905
|
return;
|
|
132915
132906
|
}
|
|
132916
132907
|
const current3 = loadSettings();
|
|
@@ -132919,7 +132910,7 @@ async function ensureDefaultCodingAgents() {
|
|
|
132919
132910
|
current3.defaultCodingAgent = detected[0].id;
|
|
132920
132911
|
}
|
|
132921
132912
|
saveSettings(current3);
|
|
132922
|
-
|
|
132913
|
+
log89.info("Enabled %d coding agent(s); default = %s", detected.length, current3.defaultCodingAgent);
|
|
132923
132914
|
}
|
|
132924
132915
|
function ensureNotificationDefaults() {
|
|
132925
132916
|
const settings3 = loadSettings();
|
|
@@ -132931,7 +132922,7 @@ function ensureNotificationDefaults() {
|
|
|
132931
132922
|
...settings3,
|
|
132932
132923
|
notifications: { ...notifications, soundOnNeedsAttention: true }
|
|
132933
132924
|
});
|
|
132934
|
-
|
|
132925
|
+
log89.info("Set default notifications.soundOnNeedsAttention = true");
|
|
132935
132926
|
}
|
|
132936
132927
|
function migrateAgentDefaultMode() {
|
|
132937
132928
|
const settings3 = loadSettings();
|
|
@@ -132939,15 +132930,15 @@ function migrateAgentDefaultMode() {
|
|
|
132939
132930
|
const mode = agentModeFromVia(settings3.cli?.defaultVia);
|
|
132940
132931
|
if (!mode) return;
|
|
132941
132932
|
saveSettings({ ...settings3, agents: { ...settings3.agents, defaultMode: mode } });
|
|
132942
|
-
|
|
132933
|
+
log89.info("Migrated cli.defaultVia to agents.defaultMode = %s", mode);
|
|
132943
132934
|
}
|
|
132944
132935
|
async function ensureSkillsInstalled() {
|
|
132945
132936
|
try {
|
|
132946
|
-
const result = await installSkills2({ log:
|
|
132937
|
+
const result = await installSkills2({ log: log89 });
|
|
132947
132938
|
const wrote = result.written.length + result.updated.length;
|
|
132948
132939
|
const linkChange = result.linked.length;
|
|
132949
132940
|
if (wrote > 0 || linkChange > 0 || result.conflicts.length > 0) {
|
|
132950
|
-
|
|
132941
|
+
log89.info(
|
|
132951
132942
|
"Synced CLI skills (shared: %d written, %d updated, %d unchanged; symlinks: %d created, %d already-linked, %d conflicts, %d skipped)",
|
|
132952
132943
|
result.written.length,
|
|
132953
132944
|
result.updated.length,
|
|
@@ -132959,7 +132950,7 @@ async function ensureSkillsInstalled() {
|
|
|
132959
132950
|
);
|
|
132960
132951
|
}
|
|
132961
132952
|
} catch (err) {
|
|
132962
|
-
|
|
132953
|
+
log89.warn("Failed to sync CLI skills: %s", err instanceof Error ? err.message : String(err));
|
|
132963
132954
|
}
|
|
132964
132955
|
}
|
|
132965
132956
|
var SetupService = class {
|
|
@@ -132980,7 +132971,7 @@ init_worktree_service();
|
|
|
132980
132971
|
function logCrash(message) {
|
|
132981
132972
|
try {
|
|
132982
132973
|
mkdirSync11(bandHome(), { recursive: true });
|
|
132983
|
-
appendFileSync2(
|
|
132974
|
+
appendFileSync2(join58(bandHome(), "server.log"), message, "utf-8");
|
|
132984
132975
|
} catch {
|
|
132985
132976
|
}
|
|
132986
132977
|
}
|
|
@@ -133020,9 +133011,9 @@ function resolveUiDir() {
|
|
|
133020
133011
|
if (explicit) return resolve14(explicit);
|
|
133021
133012
|
const candidates = [
|
|
133022
133013
|
resolve14(SERVER_ROOT, "..", "..", "web", "dist", "client"),
|
|
133023
|
-
|
|
133014
|
+
join58(SERVER_ROOT, "client")
|
|
133024
133015
|
];
|
|
133025
|
-
return candidates.find((dir) => existsSync18(
|
|
133016
|
+
return candidates.find((dir) => existsSync18(join58(dir, "_shell.html"))) ?? candidates[1];
|
|
133026
133017
|
}
|
|
133027
133018
|
var clientDir = resolveUiDir();
|
|
133028
133019
|
var uiRoot = process.env.BAND_UI_ROOT ? resolve14(process.env.BAND_UI_ROOT) : resolve14(SERVER_ROOT, "..", "web");
|
|
@@ -133073,7 +133064,7 @@ function getOpenApiSpec() {
|
|
|
133073
133064
|
if (isDev) {
|
|
133074
133065
|
const { generateOpenAPIDocument } = await import("@trpc/openapi");
|
|
133075
133066
|
const doc = await generateOpenAPIDocument(
|
|
133076
|
-
|
|
133067
|
+
join58(SERVER_ROOT, "src", "server", "api", "router.ts"),
|
|
133077
133068
|
{
|
|
133078
133069
|
title: "Band API",
|
|
133079
133070
|
version: "1.0.0"
|
|
@@ -133082,7 +133073,7 @@ function getOpenApiSpec() {
|
|
|
133082
133073
|
doc.servers = [{ url: "/trpc" }];
|
|
133083
133074
|
return JSON.stringify(doc, null, 2);
|
|
133084
133075
|
}
|
|
133085
|
-
const openApiDoc = JSON.parse(readFileSync12(
|
|
133076
|
+
const openApiDoc = JSON.parse(readFileSync12(join58(SERVER_ROOT, "openapi.json"), "utf-8"));
|
|
133086
133077
|
openApiDoc.servers = [{ url: "/trpc" }];
|
|
133087
133078
|
return JSON.stringify(openApiDoc, null, 2);
|
|
133088
133079
|
})().catch((err) => {
|
|
@@ -133098,6 +133089,13 @@ function getCachedScalarHtml() {
|
|
|
133098
133089
|
_scalarHtml = getScalarHtml("/api/openapi.json");
|
|
133099
133090
|
return _scalarHtml;
|
|
133100
133091
|
}
|
|
133092
|
+
function hostedFileHeaders(contentType) {
|
|
133093
|
+
const headers = { "X-Content-Type-Options": "nosniff" };
|
|
133094
|
+
if (/^(text\/html|image\/svg\+xml)\b/.test(contentType)) {
|
|
133095
|
+
headers["Content-Security-Policy"] = "sandbox allow-scripts";
|
|
133096
|
+
}
|
|
133097
|
+
return headers;
|
|
133098
|
+
}
|
|
133101
133099
|
function serveStaticFile(res, root, subdir, rawFilename) {
|
|
133102
133100
|
const filename = basename7(decodeURIComponent(rawFilename));
|
|
133103
133101
|
if (!filename || filename.includes("..")) {
|
|
@@ -133105,14 +133103,21 @@ function serveStaticFile(res, root, subdir, rawFilename) {
|
|
|
133105
133103
|
res.end("Bad request");
|
|
133106
133104
|
return;
|
|
133107
133105
|
}
|
|
133108
|
-
const filePath =
|
|
133106
|
+
const filePath = join58(root, subdir, filename);
|
|
133109
133107
|
try {
|
|
133108
|
+
const dir = realpathSync7(join58(root, subdir));
|
|
133109
|
+
if (!realpathSync7(filePath).startsWith(dir + sep10)) {
|
|
133110
|
+
res.writeHead(404);
|
|
133111
|
+
res.end("Not found");
|
|
133112
|
+
return;
|
|
133113
|
+
}
|
|
133110
133114
|
const fileStat = statSync16(filePath);
|
|
133111
133115
|
const contentType = mimeTypeFromFilename(filename);
|
|
133112
133116
|
res.writeHead(200, {
|
|
133113
133117
|
"Content-Type": contentType,
|
|
133114
133118
|
"Content-Length": fileStat.size.toString(),
|
|
133115
|
-
"Cache-Control": "private, max-age=86400"
|
|
133119
|
+
"Cache-Control": "private, max-age=86400",
|
|
133120
|
+
...hostedFileHeaders(contentType)
|
|
133116
133121
|
});
|
|
133117
133122
|
createReadStream6(filePath).pipe(res);
|
|
133118
133123
|
} catch {
|
|
@@ -133120,18 +133125,20 @@ function serveStaticFile(res, root, subdir, rawFilename) {
|
|
|
133120
133125
|
res.end("Not found");
|
|
133121
133126
|
}
|
|
133122
133127
|
}
|
|
133123
|
-
async function serveHostedFile(res, kind, worktreeId4, rawName) {
|
|
133128
|
+
async function serveHostedFile(res, kind, worktreeId4, rawName, chatId) {
|
|
133124
133129
|
if (hostRegistry.hostFor(worktreeId4).id === hostRegistry.local.id) return false;
|
|
133125
|
-
const file3 = await openHostedFile(kind, worktreeId4, rawName);
|
|
133130
|
+
const file3 = await openHostedFile(kind, worktreeId4, rawName, chatId);
|
|
133126
133131
|
if (!file3) {
|
|
133127
133132
|
res.writeHead(404);
|
|
133128
133133
|
res.end("Not found");
|
|
133129
133134
|
return true;
|
|
133130
133135
|
}
|
|
133136
|
+
const contentType = mimeTypeFromFilename(basename7(decodeURIComponent(rawName)));
|
|
133131
133137
|
res.writeHead(200, {
|
|
133132
|
-
"Content-Type":
|
|
133138
|
+
"Content-Type": contentType,
|
|
133133
133139
|
"Content-Length": file3.size.toString(),
|
|
133134
|
-
"Cache-Control": "private, max-age=86400"
|
|
133140
|
+
"Cache-Control": "private, max-age=86400",
|
|
133141
|
+
...hostedFileHeaders(contentType)
|
|
133135
133142
|
});
|
|
133136
133143
|
pipeline2(
|
|
133137
133144
|
Readable2.from(file3.stream, { objectMode: false, highWaterMark: 64 * 1024 }),
|
|
@@ -133149,7 +133156,7 @@ async function serveWorktreeFile(res, worktreeId4, rawPath, extraHeaders = {}, v
|
|
|
133149
133156
|
return;
|
|
133150
133157
|
}
|
|
133151
133158
|
const root = worktree.worktree.path;
|
|
133152
|
-
const target = resolve14(
|
|
133159
|
+
const target = resolve14(join58(root, rawPath));
|
|
133153
133160
|
if (!target.startsWith(root + sep10) && target !== root) {
|
|
133154
133161
|
res.writeHead(400);
|
|
133155
133162
|
res.end("Bad request");
|
|
@@ -133460,7 +133467,7 @@ async function main() {
|
|
|
133460
133467
|
res.end(JSON.stringify({ status: "ok", app: "band-web-server" }));
|
|
133461
133468
|
return;
|
|
133462
133469
|
}
|
|
133463
|
-
if (handleWebAppManifest(req, res, isDev ?
|
|
133470
|
+
if (handleWebAppManifest(req, res, isDev ? join58(uiRoot, "public") : clientDir)) return;
|
|
133464
133471
|
if (req.url?.split("?")[0] === WORKER_EXCHANGE_PATH) {
|
|
133465
133472
|
await workerLinkService.handleExchange(req, res);
|
|
133466
133473
|
return;
|
|
@@ -133559,21 +133566,17 @@ async function main() {
|
|
|
133559
133566
|
return;
|
|
133560
133567
|
}
|
|
133561
133568
|
if (req.url?.startsWith("/api/shared/")) {
|
|
133562
|
-
const
|
|
133563
|
-
|
|
133564
|
-
if (slashIdx === -1) {
|
|
133569
|
+
const parsed = parseSharedPath(req.url.slice("/api/shared/".length));
|
|
133570
|
+
if (!parsed) {
|
|
133565
133571
|
res.writeHead(400);
|
|
133566
133572
|
res.end("Bad request");
|
|
133567
133573
|
return;
|
|
133568
133574
|
}
|
|
133569
|
-
const
|
|
133570
|
-
if (
|
|
133571
|
-
res.writeHead(400);
|
|
133572
|
-
res.end("Bad request");
|
|
133575
|
+
const encodedName = encodeURIComponent(parsed.name);
|
|
133576
|
+
if (await serveHostedFile(res, "shared", parsed.worktreeId, encodedName, parsed.chatId))
|
|
133573
133577
|
return;
|
|
133574
|
-
|
|
133575
|
-
|
|
133576
|
-
serveStaticFile(res, bandHome(), join59("shared", partition), rest.slice(slashIdx + 1));
|
|
133578
|
+
const subdir = parsed.chatId ? join58("shared", parsed.worktreeId, parsed.chatId) : join58("shared", parsed.worktreeId);
|
|
133579
|
+
serveStaticFile(res, bandHome(), subdir, encodedName);
|
|
133577
133580
|
return;
|
|
133578
133581
|
}
|
|
133579
133582
|
if (req.url?.startsWith("/api/worktree-file/")) {
|
|
@@ -133793,7 +133796,7 @@ async function main() {
|
|
|
133793
133796
|
if (pathname.startsWith("/_shell")) res.setHeader("Cache-Control", "no-cache");
|
|
133794
133797
|
}
|
|
133795
133798
|
});
|
|
133796
|
-
const shellPath2 =
|
|
133799
|
+
const shellPath2 = join58(clientDir, "_shell.html");
|
|
133797
133800
|
if (!existsSync18(shellPath2)) {
|
|
133798
133801
|
throw new Error(
|
|
133799
133802
|
`UI build not found at ${clientDir} (no _shell.html). Run \`pnpm build\` or pass --ui-dir <path>.`
|