@band-app/server 0.55.0 → 0.56.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client/_shell.html +0 -0
- package/dist/client/assets/{TerminalPanel-DyFsMnFK.js → TerminalPanel-Wv-LbAcs.js} +1 -1
- package/dist/client/assets/{_basePickBy-C1Ui1wUI.js → _basePickBy-CgvoOFSS.js} +1 -1
- package/dist/client/assets/{_baseUniq-TZ0JUUYF.js → _baseUniq-DF-p-6fY.js} +1 -1
- package/dist/client/assets/{arc-BKZRD7Jr.js → arc-ukMuAfYV.js} +1 -1
- package/dist/client/assets/{architectureDiagram-VXUJARFQ-C6U3vX0O.js → architectureDiagram-VXUJARFQ-BHOsjgJ7.js} +1 -1
- package/dist/client/assets/{blockDiagram-VD42YOAC-CMKfJSCq.js → blockDiagram-VD42YOAC-V0Q-tFQE.js} +1 -1
- package/dist/client/assets/{c4Diagram-YG6GDRKO-BxBYCPCn.js → c4Diagram-YG6GDRKO-BK1nC-Zr.js} +1 -1
- package/dist/client/assets/channel-C1UOZUKN.js +1 -0
- package/dist/client/assets/{chunk-4BX2VUAB-bw9X6kAI.js → chunk-4BX2VUAB-Cc2lXQih.js} +1 -1
- package/dist/client/assets/{chunk-55IACEB6-ClHgx4bC.js → chunk-55IACEB6-ByQepK2K.js} +1 -1
- package/dist/client/assets/{chunk-B4BG7PRW-Db1XzP6B.js → chunk-B4BG7PRW-BQQywZlE.js} +1 -1
- package/dist/client/assets/{chunk-DI55MBZ5-C8HzWkcQ.js → chunk-DI55MBZ5-C0Q1yI7a.js} +1 -1
- package/dist/client/assets/{chunk-FMBD7UC4-54B6Y5YM.js → chunk-FMBD7UC4-G_Ta25S5.js} +1 -1
- package/dist/client/assets/{chunk-QN33PNHL-BttimAfW.js → chunk-QN33PNHL-vrj5lpjf.js} +1 -1
- package/dist/client/assets/{chunk-QZHKN3VN-BoejelHz.js → chunk-QZHKN3VN-DIoJiZ6Q.js} +1 -1
- package/dist/client/assets/{chunk-TZMSLE5B-CDFjN9wj.js → chunk-TZMSLE5B-DbF2At2q.js} +1 -1
- package/dist/client/assets/classDiagram-2ON5EDUG-CBwXamAz.js +1 -0
- package/dist/client/assets/classDiagram-v2-WZHVMYZB-CBwXamAz.js +1 -0
- package/dist/client/assets/clone-CnowCdRV.js +1 -0
- package/dist/client/assets/{cose-bilkent-S5V4N54A-VQAtNwQc.js → cose-bilkent-S5V4N54A-DmniYlnr.js} +1 -1
- package/dist/client/assets/{dagre-6UL2VRFP-BbY85-fg.js → dagre-6UL2VRFP-xNi8WScD.js} +1 -1
- package/dist/client/assets/{diagram-PSM6KHXK-ILb8cZAw.js → diagram-PSM6KHXK-CL4dq7uj.js} +1 -1
- package/dist/client/assets/{diagram-QEK2KX5R-BGiFNVyl.js → diagram-QEK2KX5R-C7WQ7eoU.js} +1 -1
- package/dist/client/assets/{diagram-S2PKOQOG-CccJTBEx.js → diagram-S2PKOQOG-Cl6jL5JB.js} +1 -1
- package/dist/client/assets/{erDiagram-Q2GNP2WA-CkfZ33hi.js → erDiagram-Q2GNP2WA-DOCd-FW1.js} +1 -1
- package/dist/client/assets/{flowDiagram-NV44I4VS-Mh9EcV52.js → flowDiagram-NV44I4VS-BcjVCXzs.js} +1 -1
- package/dist/client/assets/{ganttDiagram-JELNMOA3-Cyw35fle.js → ganttDiagram-JELNMOA3-Cp5IVV1X.js} +1 -1
- package/dist/client/assets/{gitGraphDiagram-V2S2FVAM-B_pqKxKc.js → gitGraphDiagram-V2S2FVAM-D81a2lqP.js} +1 -1
- package/dist/client/assets/{graph-9t0DxPCF.js → graph-DAQsyN1O.js} +1 -1
- package/dist/client/assets/{highlighted-body-B3W2YXNL-BoRk8xol.js → highlighted-body-B3W2YXNL-BHdTpazT.js} +1 -1
- package/dist/client/assets/{index-q1D5zrY_.js → index-4wTCyGVZ.js} +1 -1
- package/dist/client/assets/{index-BwCTnd17.js → index-BIBgEJc_.js} +1 -1
- package/dist/client/assets/{index-D8L39ca2.js → index-BbUBghw-.js} +1 -1
- package/dist/client/assets/{index-Ddtx5YHI.js → index-C69wUmqS.js} +1 -1
- package/dist/client/assets/{index-Bq4KlIgZ.js → index-CKC2JTdn.js} +1 -1
- package/dist/client/assets/{index-BHbtQqNn.js → index-CYW-8-2k.js} +1 -1
- package/dist/client/assets/{index-DyQAzRmj.js → index-CzW0lrV1.js} +1 -1
- package/dist/client/assets/{index-B4gaIFLM.js → index-D6mUuQso.js} +1 -1
- package/dist/client/assets/{index-B9OAdTCy.js → index-DCOA8K1E.js} +1 -1
- package/dist/client/assets/{index-0OIfn_16.js → index-DFnmEpf1.js} +1 -1
- package/dist/client/assets/{index-EhAKhw5f.js → index-DcgU8Py3.js} +1 -1
- package/dist/client/assets/{index-DicOq_Sf.js → index-DdbCWPks.js} +1 -1
- package/dist/client/assets/{index-CtGnlQ-q.js → index-U7nQzvUZ.js} +1 -1
- package/dist/client/assets/{infoDiagram-HS3SLOUP-BpXpceBS.js → infoDiagram-HS3SLOUP-Cm5s9O89.js} +1 -1
- package/dist/client/assets/{journeyDiagram-XKPGCS4Q-CUzBsDC2.js → journeyDiagram-XKPGCS4Q-BEmfY1L5.js} +1 -1
- package/dist/client/assets/{kanban-definition-3W4ZIXB7-d7CaBEND.js → kanban-definition-3W4ZIXB7-BR4wUQUP.js} +1 -1
- package/dist/client/assets/{layout-D8LvZDRj.js → layout-eg8UUTsn.js} +1 -1
- package/dist/client/assets/{main-BIldwfya.js → main-lic-ksql.js} +247 -247
- package/dist/client/assets/{mindmap-definition-VGOIOE7T-CkyVVJ9w.js → mindmap-definition-VGOIOE7T-aO87fIIJ.js} +1 -1
- package/dist/client/assets/{pieDiagram-ADFJNKIX-UGEIX01f.js → pieDiagram-ADFJNKIX-D1-R_4cR.js} +1 -1
- package/dist/client/assets/{quadrantDiagram-AYHSOK5B-C9PM1qGp.js → quadrantDiagram-AYHSOK5B-DG_jZYS7.js} +1 -1
- package/dist/client/assets/{requirementDiagram-UZGBJVZJ-BmJorjE0.js → requirementDiagram-UZGBJVZJ-BtxpIvi0.js} +1 -1
- package/dist/client/assets/{sankeyDiagram-TZEHDZUN-DK1YkHOf.js → sankeyDiagram-TZEHDZUN-CEZw5ngO.js} +1 -1
- package/dist/client/assets/{sequenceDiagram-WL72ISMW-CMalVkVp.js → sequenceDiagram-WL72ISMW-Da7IJD8T.js} +1 -1
- package/dist/client/assets/{stateDiagram-FKZM4ZOC-CtDoLljP.js → stateDiagram-FKZM4ZOC-D9MZaz-Z.js} +1 -1
- package/dist/client/assets/stateDiagram-v2-4FDKWEC3-BZauII8k.js +1 -0
- package/dist/client/assets/{timeline-definition-IT6M3QCI-Vy5fVSzE.js → timeline-definition-IT6M3QCI-Dpy1CJBt.js} +1 -1
- package/dist/client/assets/{treemap-GDKQZRPO-DN8hAqbn.js → treemap-GDKQZRPO-CwxFs7qg.js} +1 -1
- package/dist/client/assets/{worktree._worktreeId-BjqfB2FM.js → worktree._worktreeId-BrMMD4KZ.js} +1 -1
- package/dist/client/assets/{worktree._worktreeId-enSNl8Hs.js → worktree._worktreeId-D8tRL5dj.js} +1 -1
- package/dist/client/assets/{xychartDiagram-PRI3JC2R-Dl5pLjgP.js → xychartDiagram-PRI3JC2R-C42Fu89p.js} +1 -1
- package/dist/openapi.json +30 -27
- package/dist/start-server.mjs +456 -415
- package/package.json +10 -10
- package/dist/client/assets/channel-BJXLlcqp.js +0 -1
- package/dist/client/assets/classDiagram-2ON5EDUG-27E8Epaa.js +0 -1
- package/dist/client/assets/classDiagram-v2-WZHVMYZB-27E8Epaa.js +0 -1
- package/dist/client/assets/clone-DTRMs_1C.js +0 -1
- package/dist/client/assets/stateDiagram-v2-4FDKWEC3-Bu9w4Lt2.js +0 -1
package/dist/start-server.mjs
CHANGED
|
@@ -2989,11 +2989,11 @@ var require_tools = __commonJS({
|
|
|
2989
2989
|
}
|
|
2990
2990
|
}
|
|
2991
2991
|
}
|
|
2992
|
-
function buildFormatters(level, bindings,
|
|
2992
|
+
function buildFormatters(level, bindings, log95) {
|
|
2993
2993
|
return {
|
|
2994
2994
|
level,
|
|
2995
2995
|
bindings,
|
|
2996
|
-
log:
|
|
2996
|
+
log: log95
|
|
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: log95 } = options.formatters;
|
|
3380
3380
|
instance[formattersSym] = buildFormatters(
|
|
3381
3381
|
level || formatters.level,
|
|
3382
3382
|
chindings || resetChildingsFormatter,
|
|
3383
|
-
|
|
3383
|
+
log95 || formatters.log
|
|
3384
3384
|
);
|
|
3385
3385
|
} else {
|
|
3386
3386
|
instance[formattersSym] = buildFormatters(
|
|
@@ -17542,6 +17542,104 @@ var init_speech_transcription = __esm({
|
|
|
17542
17542
|
}
|
|
17543
17543
|
});
|
|
17544
17544
|
|
|
17545
|
+
// ../../packages/worktree-ops/src/http-files.ts
|
|
17546
|
+
import { extname } from "node:path";
|
|
17547
|
+
function parseByteRange(header, size) {
|
|
17548
|
+
const match = /^bytes=(\d*)-(\d*)$/.exec(header?.trim() ?? "");
|
|
17549
|
+
if (!match || match[1] === "" && match[2] === "") return null;
|
|
17550
|
+
if (match[1] !== "" && match[2] !== "" && Number(match[2]) < Number(match[1])) return null;
|
|
17551
|
+
let start;
|
|
17552
|
+
let end;
|
|
17553
|
+
if (match[1] === "") {
|
|
17554
|
+
const length = Number(match[2]);
|
|
17555
|
+
if (length === 0) return "unsatisfiable";
|
|
17556
|
+
start = Math.max(0, size - length);
|
|
17557
|
+
end = size - 1;
|
|
17558
|
+
} else {
|
|
17559
|
+
start = Number(match[1]);
|
|
17560
|
+
end = match[2] === "" ? size - 1 : Math.min(Number(match[2]), size - 1);
|
|
17561
|
+
}
|
|
17562
|
+
if (start >= size || start > end) return "unsatisfiable";
|
|
17563
|
+
return { start, end };
|
|
17564
|
+
}
|
|
17565
|
+
function attachmentDisposition(filename) {
|
|
17566
|
+
const clean = filename.replace(/[/\\]/g, "_") || "download";
|
|
17567
|
+
const ascii = clean.replace(/[^\x20-\x7e]/g, "_").replace(/["%;]/g, "_");
|
|
17568
|
+
const encoded = encodeURIComponent(clean).replace(
|
|
17569
|
+
/['()*]/g,
|
|
17570
|
+
(c) => `%${c.charCodeAt(0).toString(16).toUpperCase()}`
|
|
17571
|
+
);
|
|
17572
|
+
return `attachment; filename="${ascii}"; filename*=UTF-8''${encoded}`;
|
|
17573
|
+
}
|
|
17574
|
+
function mimeTypeFromFilename(filename) {
|
|
17575
|
+
const ext = extname(filename).toLowerCase();
|
|
17576
|
+
return MIME_TYPES[ext] || "application/octet-stream";
|
|
17577
|
+
}
|
|
17578
|
+
function hostedFileHeaders(contentType) {
|
|
17579
|
+
const headers = { "X-Content-Type-Options": "nosniff" };
|
|
17580
|
+
if (/^(text\/html|image\/svg\+xml)\b/.test(contentType)) {
|
|
17581
|
+
headers["Content-Security-Policy"] = "sandbox allow-scripts";
|
|
17582
|
+
}
|
|
17583
|
+
return headers;
|
|
17584
|
+
}
|
|
17585
|
+
function parseSharedPath(rest) {
|
|
17586
|
+
const raw = rest.split("?")[0].split("/");
|
|
17587
|
+
if (raw.length !== 2 && raw.length !== 3) return null;
|
|
17588
|
+
const parts = [];
|
|
17589
|
+
for (const segment of raw) {
|
|
17590
|
+
let decoded;
|
|
17591
|
+
try {
|
|
17592
|
+
decoded = decodeURIComponent(segment);
|
|
17593
|
+
} catch {
|
|
17594
|
+
return null;
|
|
17595
|
+
}
|
|
17596
|
+
if (!decoded || decoded === "." || decoded === ".." || /[/\\\0]/.test(decoded)) return null;
|
|
17597
|
+
parts.push(decoded);
|
|
17598
|
+
}
|
|
17599
|
+
return parts.length === 3 ? { worktreeId: parts[0], chatId: parts[1], name: parts[2] } : { worktreeId: parts[0], name: parts[1] };
|
|
17600
|
+
}
|
|
17601
|
+
var MIME_TYPES;
|
|
17602
|
+
var init_http_files = __esm({
|
|
17603
|
+
"../../packages/worktree-ops/src/http-files.ts"() {
|
|
17604
|
+
"use strict";
|
|
17605
|
+
MIME_TYPES = {
|
|
17606
|
+
".png": "image/png",
|
|
17607
|
+
".jpg": "image/jpeg",
|
|
17608
|
+
".jpeg": "image/jpeg",
|
|
17609
|
+
".gif": "image/gif",
|
|
17610
|
+
".webp": "image/webp",
|
|
17611
|
+
".svg": "image/svg+xml",
|
|
17612
|
+
".ico": "image/x-icon",
|
|
17613
|
+
".bmp": "image/bmp",
|
|
17614
|
+
".avif": "image/avif",
|
|
17615
|
+
".mp4": "video/mp4",
|
|
17616
|
+
".m4v": "video/mp4",
|
|
17617
|
+
".mov": "video/quicktime",
|
|
17618
|
+
".webm": "video/webm",
|
|
17619
|
+
".ogv": "video/ogg",
|
|
17620
|
+
".pdf": "application/pdf",
|
|
17621
|
+
".json": "application/json",
|
|
17622
|
+
".txt": "text/plain",
|
|
17623
|
+
".md": "text/markdown",
|
|
17624
|
+
".csv": "text/csv",
|
|
17625
|
+
".html": "text/html; charset=utf-8",
|
|
17626
|
+
".htm": "text/html; charset=utf-8",
|
|
17627
|
+
".css": "text/css; charset=utf-8",
|
|
17628
|
+
".js": "text/javascript; charset=utf-8",
|
|
17629
|
+
".mjs": "text/javascript; charset=utf-8",
|
|
17630
|
+
".woff": "font/woff",
|
|
17631
|
+
".woff2": "font/woff2",
|
|
17632
|
+
".ttf": "font/ttf",
|
|
17633
|
+
".otf": "font/otf",
|
|
17634
|
+
".ts": "application/typescript",
|
|
17635
|
+
".xml": "application/xml",
|
|
17636
|
+
".yaml": "application/x-yaml",
|
|
17637
|
+
".yml": "application/x-yaml",
|
|
17638
|
+
".zip": "application/zip"
|
|
17639
|
+
};
|
|
17640
|
+
}
|
|
17641
|
+
});
|
|
17642
|
+
|
|
17545
17643
|
// ../../node_modules/.pnpm/@trpc+server@11.12.0_typescript@5.9.3/node_modules/@trpc/server/dist/codes-DagpWZLc.mjs
|
|
17546
17644
|
function mergeWithoutOverrides(obj1, ...objs) {
|
|
17547
17645
|
const newObj = Object.assign(emptyObject(), obj1);
|
|
@@ -65815,27 +65913,12 @@ async function agentExtraDirs(worktreeId4) {
|
|
|
65815
65913
|
function sharedFileUrl(worktreeId4, chatId, filename) {
|
|
65816
65914
|
return `/api/shared/${encodeURIComponent(worktreeId4)}/${encodeURIComponent(chatId)}/${encodeURIComponent(filename)}`;
|
|
65817
65915
|
}
|
|
65818
|
-
function parseSharedPath(rest) {
|
|
65819
|
-
const raw = rest.split("?")[0].split("/");
|
|
65820
|
-
if (raw.length !== 2 && raw.length !== 3) return null;
|
|
65821
|
-
const parts = [];
|
|
65822
|
-
for (const segment of raw) {
|
|
65823
|
-
let decoded;
|
|
65824
|
-
try {
|
|
65825
|
-
decoded = decodeURIComponent(segment);
|
|
65826
|
-
} catch {
|
|
65827
|
-
return null;
|
|
65828
|
-
}
|
|
65829
|
-
if (!decoded || decoded === "." || decoded === ".." || /[/\\\0]/.test(decoded)) return null;
|
|
65830
|
-
parts.push(decoded);
|
|
65831
|
-
}
|
|
65832
|
-
return parts.length === 3 ? { worktreeId: parts[0], chatId: parts[1], name: parts[2] } : { worktreeId: parts[0], name: parts[1] };
|
|
65833
|
-
}
|
|
65834
65916
|
var init_shared_dir = __esm({
|
|
65835
65917
|
"src/server/services/_utils/shared-dir.ts"() {
|
|
65836
65918
|
"use strict";
|
|
65837
65919
|
init_registry();
|
|
65838
65920
|
init_state();
|
|
65921
|
+
init_http_files();
|
|
65839
65922
|
}
|
|
65840
65923
|
});
|
|
65841
65924
|
|
|
@@ -71332,50 +71415,10 @@ var init_chat_status_service = __esm({
|
|
|
71332
71415
|
});
|
|
71333
71416
|
|
|
71334
71417
|
// src/server/services/_utils/mime-types.ts
|
|
71335
|
-
import { extname } from "node:path";
|
|
71336
|
-
function mimeTypeFromFilename(filename) {
|
|
71337
|
-
const ext = extname(filename).toLowerCase();
|
|
71338
|
-
return MIME_TYPES[ext] || "application/octet-stream";
|
|
71339
|
-
}
|
|
71340
|
-
var MIME_TYPES;
|
|
71341
71418
|
var init_mime_types = __esm({
|
|
71342
71419
|
"src/server/services/_utils/mime-types.ts"() {
|
|
71343
71420
|
"use strict";
|
|
71344
|
-
|
|
71345
|
-
".png": "image/png",
|
|
71346
|
-
".jpg": "image/jpeg",
|
|
71347
|
-
".jpeg": "image/jpeg",
|
|
71348
|
-
".gif": "image/gif",
|
|
71349
|
-
".webp": "image/webp",
|
|
71350
|
-
".svg": "image/svg+xml",
|
|
71351
|
-
".ico": "image/x-icon",
|
|
71352
|
-
".bmp": "image/bmp",
|
|
71353
|
-
".avif": "image/avif",
|
|
71354
|
-
".mp4": "video/mp4",
|
|
71355
|
-
".m4v": "video/mp4",
|
|
71356
|
-
".mov": "video/quicktime",
|
|
71357
|
-
".webm": "video/webm",
|
|
71358
|
-
".ogv": "video/ogg",
|
|
71359
|
-
".pdf": "application/pdf",
|
|
71360
|
-
".json": "application/json",
|
|
71361
|
-
".txt": "text/plain",
|
|
71362
|
-
".md": "text/markdown",
|
|
71363
|
-
".csv": "text/csv",
|
|
71364
|
-
".html": "text/html; charset=utf-8",
|
|
71365
|
-
".htm": "text/html; charset=utf-8",
|
|
71366
|
-
".css": "text/css; charset=utf-8",
|
|
71367
|
-
".js": "text/javascript; charset=utf-8",
|
|
71368
|
-
".mjs": "text/javascript; charset=utf-8",
|
|
71369
|
-
".woff": "font/woff",
|
|
71370
|
-
".woff2": "font/woff2",
|
|
71371
|
-
".ttf": "font/ttf",
|
|
71372
|
-
".otf": "font/otf",
|
|
71373
|
-
".ts": "application/typescript",
|
|
71374
|
-
".xml": "application/xml",
|
|
71375
|
-
".yaml": "application/x-yaml",
|
|
71376
|
-
".yml": "application/x-yaml",
|
|
71377
|
-
".zip": "application/zip"
|
|
71378
|
-
};
|
|
71421
|
+
init_http_files();
|
|
71379
71422
|
}
|
|
71380
71423
|
});
|
|
71381
71424
|
|
|
@@ -75358,8 +75401,8 @@ var init_environment_builds = __esm({
|
|
|
75358
75401
|
get(id) {
|
|
75359
75402
|
return getDb().select().from(environmentBuilds).where(eq2(environmentBuilds.id, id)).get();
|
|
75360
75403
|
}
|
|
75361
|
-
setLog(id,
|
|
75362
|
-
getDb().update(environmentBuilds).set({ log:
|
|
75404
|
+
setLog(id, log95) {
|
|
75405
|
+
getDb().update(environmentBuilds).set({ log: log95 }).where(eq2(environmentBuilds.id, id)).run();
|
|
75363
75406
|
}
|
|
75364
75407
|
finish(id, result) {
|
|
75365
75408
|
getDb().update(environmentBuilds).set({
|
|
@@ -75727,32 +75770,32 @@ ${this.text.slice(-MAX_LOG_BYTES)}`;
|
|
|
75727
75770
|
}
|
|
75728
75771
|
// ---- running ---------------------------------------------------------------
|
|
75729
75772
|
async run(row, plan) {
|
|
75730
|
-
const
|
|
75773
|
+
const log95 = new BuildLog(row.id, (id, text4) => this.queries.setLog(id, text4));
|
|
75731
75774
|
let tmp = null;
|
|
75732
75775
|
const container = `band-env-${row.id.slice(0, 12)}`;
|
|
75733
75776
|
let failure4 = null;
|
|
75734
75777
|
try {
|
|
75735
|
-
|
|
75736
|
-
|
|
75778
|
+
log95.add(`Building ${plan.tag} for ${plan.repo} at ${plan.ref} (${plan.commit.slice(0, 12)})`);
|
|
75779
|
+
log95.flush();
|
|
75737
75780
|
tmp = await plan.host.fs.mkdtemp("band-env-");
|
|
75738
|
-
await this.exportCheckout(plan, tmp,
|
|
75739
|
-
const toolchain = await this.buildToolchain(plan, tmp,
|
|
75740
|
-
const layered = await this.addWorkerLayer(plan, tmp, toolchain,
|
|
75741
|
-
await this.install(plan, tmp, layered, container,
|
|
75742
|
-
if (plan.registry) await this.push(plan,
|
|
75743
|
-
|
|
75781
|
+
await this.exportCheckout(plan, tmp, log95);
|
|
75782
|
+
const toolchain = await this.buildToolchain(plan, tmp, log95);
|
|
75783
|
+
const layered = await this.addWorkerLayer(plan, tmp, toolchain, log95);
|
|
75784
|
+
await this.install(plan, tmp, layered, container, log95);
|
|
75785
|
+
if (plan.registry) await this.push(plan, log95);
|
|
75786
|
+
log95.add(`Done: ${plan.tag}`);
|
|
75744
75787
|
} catch (err) {
|
|
75745
75788
|
failure4 = err.message;
|
|
75746
|
-
|
|
75789
|
+
log95.add(`FAILED: ${failure4}`);
|
|
75747
75790
|
}
|
|
75748
|
-
await this.exec(plan.host, "docker", ["rm", "--force", container],
|
|
75791
|
+
await this.exec(plan.host, "docker", ["rm", "--force", container], log95, { quiet: true }).catch(
|
|
75749
75792
|
() => void 0
|
|
75750
75793
|
);
|
|
75751
75794
|
await this.exec(
|
|
75752
75795
|
plan.host,
|
|
75753
75796
|
"docker",
|
|
75754
75797
|
["rmi", toolchainTag(plan.repo, plan.key), layeredTag(plan.repo, plan.key)],
|
|
75755
|
-
|
|
75798
|
+
log95,
|
|
75756
75799
|
{ quiet: true }
|
|
75757
75800
|
).catch(() => void 0);
|
|
75758
75801
|
if (tmp) await plan.host.fs.rm(tmp, { recursive: true, force: true }).catch(() => void 0);
|
|
@@ -75761,14 +75804,14 @@ ${this.text.slice(-MAX_LOG_BYTES)}`;
|
|
|
75761
75804
|
this.queries.finish(row.id, {
|
|
75762
75805
|
status: "ready",
|
|
75763
75806
|
image: plan.tag,
|
|
75764
|
-
log:
|
|
75807
|
+
log: log95.toString(),
|
|
75765
75808
|
at: Date.now()
|
|
75766
75809
|
});
|
|
75767
75810
|
} else {
|
|
75768
75811
|
this.queries.finish(row.id, {
|
|
75769
75812
|
status: "failed",
|
|
75770
75813
|
error: failure4.slice(0, 2e3),
|
|
75771
|
-
log:
|
|
75814
|
+
log: log95.toString(),
|
|
75772
75815
|
at: Date.now()
|
|
75773
75816
|
});
|
|
75774
75817
|
}
|
|
@@ -75777,9 +75820,9 @@ ${this.text.slice(-MAX_LOG_BYTES)}`;
|
|
|
75777
75820
|
}
|
|
75778
75821
|
}
|
|
75779
75822
|
/** Runs a command on the builder host, adding it and its output to the log. */
|
|
75780
|
-
async exec(host, tool2, args,
|
|
75823
|
+
async exec(host, tool2, args, log95, options = {}) {
|
|
75781
75824
|
const bin = tool2 === "docker" ? this.dockerBin(host) : tool2 === "devcontainer" ? this.devcontainerBin(host) : "git";
|
|
75782
|
-
if (!options.quiet)
|
|
75825
|
+
if (!options.quiet) log95.add(`$ ${tool2} ${args.join(" ")}`);
|
|
75783
75826
|
try {
|
|
75784
75827
|
const out = await host.exec(bin, args, {
|
|
75785
75828
|
cwd: options.cwd,
|
|
@@ -75787,35 +75830,35 @@ ${this.text.slice(-MAX_LOG_BYTES)}`;
|
|
|
75787
75830
|
timeoutMs: envNumber("BAND_ENVIRONMENT_BUILD_TIMEOUT_MS", DEFAULT_STEP_TIMEOUT_MS)
|
|
75788
75831
|
});
|
|
75789
75832
|
if (!options.quiet) {
|
|
75790
|
-
if (out.stdout.trim())
|
|
75791
|
-
if (out.stderr.trim())
|
|
75792
|
-
|
|
75833
|
+
if (out.stdout.trim()) log95.add(out.stdout.trimEnd());
|
|
75834
|
+
if (out.stderr.trim()) log95.add(out.stderr.trimEnd());
|
|
75835
|
+
log95.flush();
|
|
75793
75836
|
}
|
|
75794
75837
|
return out.stdout;
|
|
75795
75838
|
} catch (err) {
|
|
75796
75839
|
if (!options.quiet) {
|
|
75797
|
-
|
|
75798
|
-
|
|
75840
|
+
log95.add(err.message);
|
|
75841
|
+
log95.flush();
|
|
75799
75842
|
}
|
|
75800
75843
|
throw new Error(`${tool2} ${args[0] ?? ""} failed: ${firstLine(err.message)}`);
|
|
75801
75844
|
}
|
|
75802
75845
|
}
|
|
75803
75846
|
/** Writes the default branch's files, with no `.git`, to `<tmp>/src`. */
|
|
75804
|
-
async exportCheckout(plan, tmp,
|
|
75847
|
+
async exportCheckout(plan, tmp, log95) {
|
|
75805
75848
|
const src = posix4.join(tmp, "src");
|
|
75806
75849
|
await plan.host.fs.mkdir(src);
|
|
75807
75850
|
const index3 = posix4.join(tmp, "index");
|
|
75808
|
-
await this.exec(plan.host, "git", ["read-tree", plan.ref],
|
|
75851
|
+
await this.exec(plan.host, "git", ["read-tree", plan.ref], log95, {
|
|
75809
75852
|
cwd: plan.repoPath,
|
|
75810
75853
|
env: { GIT_INDEX_FILE: index3 }
|
|
75811
75854
|
});
|
|
75812
|
-
await this.exec(plan.host, "git", ["checkout-index", "--all", `--prefix=${src}/`],
|
|
75855
|
+
await this.exec(plan.host, "git", ["checkout-index", "--all", `--prefix=${src}/`], log95, {
|
|
75813
75856
|
cwd: plan.repoPath,
|
|
75814
75857
|
env: { GIT_INDEX_FILE: index3 }
|
|
75815
75858
|
});
|
|
75816
75859
|
}
|
|
75817
75860
|
/** Layer 2: returns the tag of an image holding the repo's toolchain. */
|
|
75818
|
-
async buildToolchain(plan, tmp,
|
|
75861
|
+
async buildToolchain(plan, tmp, log95) {
|
|
75819
75862
|
const build = plan.environment.build;
|
|
75820
75863
|
const src = posix4.join(tmp, "src");
|
|
75821
75864
|
const tag = toolchainTag(plan.repo, plan.key);
|
|
@@ -75824,7 +75867,7 @@ ${this.text.slice(-MAX_LOG_BYTES)}`;
|
|
|
75824
75867
|
plan.host,
|
|
75825
75868
|
"docker",
|
|
75826
75869
|
dockerBuildArgs({ checkout: src, dockerfile: build.dockerfile, tag }),
|
|
75827
|
-
|
|
75870
|
+
log95
|
|
75828
75871
|
);
|
|
75829
75872
|
return tag;
|
|
75830
75873
|
}
|
|
@@ -75834,7 +75877,7 @@ ${this.text.slice(-MAX_LOG_BYTES)}`;
|
|
|
75834
75877
|
plan.host,
|
|
75835
75878
|
"devcontainer",
|
|
75836
75879
|
devcontainerBuildArgs({ checkout: src, config: build.devcontainer, tag }),
|
|
75837
|
-
|
|
75880
|
+
log95
|
|
75838
75881
|
);
|
|
75839
75882
|
} catch (err) {
|
|
75840
75883
|
throw new Error(
|
|
@@ -75844,11 +75887,11 @@ ${this.text.slice(-MAX_LOG_BYTES)}`;
|
|
|
75844
75887
|
return tag;
|
|
75845
75888
|
}
|
|
75846
75889
|
const image = build?.image;
|
|
75847
|
-
await this.exec(plan.host, "docker", ["pull", image],
|
|
75890
|
+
await this.exec(plan.host, "docker", ["pull", image], log95);
|
|
75848
75891
|
return image;
|
|
75849
75892
|
}
|
|
75850
75893
|
/** Layer 1 on top of layer 2: copies the worker from the worker base image. */
|
|
75851
|
-
async addWorkerLayer(plan, tmp, toolchain,
|
|
75894
|
+
async addWorkerLayer(plan, tmp, toolchain, log95) {
|
|
75852
75895
|
const dir = posix4.join(tmp, "layer");
|
|
75853
75896
|
await plan.host.fs.mkdir(dir);
|
|
75854
75897
|
await plan.host.fs.writeFile(
|
|
@@ -75860,38 +75903,38 @@ ${this.text.slice(-MAX_LOG_BYTES)}`;
|
|
|
75860
75903
|
});
|
|
75861
75904
|
await plan.host.fs.mkdir(posix4.join(dir, "root", "work"), { recursive: true });
|
|
75862
75905
|
const tag = layeredTag(plan.repo, plan.key);
|
|
75863
|
-
await this.exec(plan.host, "docker", ["build", "--tag", tag, dir],
|
|
75906
|
+
await this.exec(plan.host, "docker", ["build", "--tag", tag, dir], log95);
|
|
75864
75907
|
return tag;
|
|
75865
75908
|
}
|
|
75866
75909
|
/** Runs `install` at the default branch inside the image and commits the result as the final tag. */
|
|
75867
|
-
async install(plan, tmp, layered, container,
|
|
75910
|
+
async install(plan, tmp, layered, container, log95) {
|
|
75868
75911
|
const install = plan.environment.install;
|
|
75869
75912
|
if (install === void 0) {
|
|
75870
|
-
await this.exec(plan.host, "docker", ["tag", layered, plan.tag],
|
|
75913
|
+
await this.exec(plan.host, "docker", ["tag", layered, plan.tag], log95);
|
|
75871
75914
|
return;
|
|
75872
75915
|
}
|
|
75873
75916
|
await this.exec(
|
|
75874
75917
|
plan.host,
|
|
75875
75918
|
"docker",
|
|
75876
75919
|
installCreateArgs({ name: container, image: layered, install }),
|
|
75877
|
-
|
|
75920
|
+
log95
|
|
75878
75921
|
);
|
|
75879
75922
|
await this.exec(
|
|
75880
75923
|
plan.host,
|
|
75881
75924
|
"docker",
|
|
75882
75925
|
["cp", `${posix4.join(tmp, "src")}/.`, `${container}:${IMAGE_WORKDIR}`],
|
|
75883
|
-
|
|
75926
|
+
log95
|
|
75884
75927
|
);
|
|
75885
|
-
await this.exec(plan.host, "docker", ["start", "--attach", container],
|
|
75928
|
+
await this.exec(plan.host, "docker", ["start", "--attach", container], log95);
|
|
75886
75929
|
await this.exec(
|
|
75887
75930
|
plan.host,
|
|
75888
75931
|
"docker",
|
|
75889
75932
|
commitArgs({ container, tag: plan.tag, key: plan.key, commit: plan.commit }),
|
|
75890
|
-
|
|
75933
|
+
log95
|
|
75891
75934
|
);
|
|
75892
75935
|
}
|
|
75893
|
-
async push(plan,
|
|
75894
|
-
await this.exec(plan.host, "docker", ["push", plan.tag],
|
|
75936
|
+
async push(plan, log95) {
|
|
75937
|
+
await this.exec(plan.host, "docker", ["push", plan.tag], log95);
|
|
75895
75938
|
}
|
|
75896
75939
|
// ---- auto trigger ----------------------------------------------------------
|
|
75897
75940
|
/**
|
|
@@ -90129,11 +90172,11 @@ var require_core = __commonJS({
|
|
|
90129
90172
|
Ajv2.ValidationError = validation_error_1.default;
|
|
90130
90173
|
Ajv2.MissingRefError = ref_error_1.default;
|
|
90131
90174
|
exports.default = Ajv2;
|
|
90132
|
-
function checkOptions(checkOpts, options, msg,
|
|
90175
|
+
function checkOptions(checkOpts, options, msg, log95 = "error") {
|
|
90133
90176
|
for (const key2 in checkOpts) {
|
|
90134
90177
|
const opt = key2;
|
|
90135
90178
|
if (opt in options)
|
|
90136
|
-
this.logger[
|
|
90179
|
+
this.logger[log95](`${msg}: option ${key2}. ${checkOpts[opt]}`);
|
|
90137
90180
|
}
|
|
90138
90181
|
}
|
|
90139
90182
|
function getSchEnv(keyRef) {
|
|
@@ -92663,6 +92706,7 @@ function createTerminalBackend(serverRoot, bandHome2) {
|
|
|
92663
92706
|
// start-server.ts
|
|
92664
92707
|
init_src4();
|
|
92665
92708
|
init_speech_transcription();
|
|
92709
|
+
init_http_files();
|
|
92666
92710
|
|
|
92667
92711
|
// ../../node_modules/.pnpm/@trpc+server@11.12.0_typescript@5.9.3/node_modules/@trpc/server/dist/adapters/fetch/index.mjs
|
|
92668
92712
|
init_getErrorShape_vC8mUXJD();
|
|
@@ -112513,9 +112557,6 @@ function throwAsTRPCError(err) {
|
|
|
112513
112557
|
init_dist();
|
|
112514
112558
|
init_zod();
|
|
112515
112559
|
|
|
112516
|
-
// src/server/services/editor-service.ts
|
|
112517
|
-
import { isAbsolute as isAbsolute5, join as join52, resolve as resolve10, sep as sep6 } from "node:path";
|
|
112518
|
-
|
|
112519
112560
|
// ../../packages/shared/src/file-location.ts
|
|
112520
112561
|
function formatFileLocation(filePath, line2, options) {
|
|
112521
112562
|
if (line2 != null && options?.lineEnd != null) return `${filePath}:${line2}-${options.lineEnd}`;
|
|
@@ -112524,12 +112565,71 @@ function formatFileLocation(filePath, line2, options) {
|
|
|
112524
112565
|
return filePath;
|
|
112525
112566
|
}
|
|
112526
112567
|
|
|
112568
|
+
// ../../packages/worktree-ops/src/resolve-path.ts
|
|
112569
|
+
init_resolver();
|
|
112570
|
+
import { isAbsolute as isAbsolute4, join as join51, resolve as resolve10, sep as sep6 } from "node:path";
|
|
112571
|
+
var PathsService = class {
|
|
112572
|
+
constructor(worktrees2) {
|
|
112573
|
+
this.worktrees = worktrees2;
|
|
112574
|
+
}
|
|
112575
|
+
async resolvePath(input3) {
|
|
112576
|
+
const worktree = this.worktrees.resolve(input3.worktreeId);
|
|
112577
|
+
if (!worktree) throw new WorktreeNotFoundError(input3.worktreeId);
|
|
112578
|
+
const resolved = await resolveTarget(worktree.host.fs, worktree.worktree.path, input3.filePath);
|
|
112579
|
+
return {
|
|
112580
|
+
exists: resolved.exists,
|
|
112581
|
+
isFile: resolved.isFile,
|
|
112582
|
+
external: !resolved.inside,
|
|
112583
|
+
worktreeRelativePath: resolved.inside ? resolved.relativePath : null
|
|
112584
|
+
};
|
|
112585
|
+
}
|
|
112586
|
+
};
|
|
112587
|
+
async function resolveTarget(fs3, root, filePath) {
|
|
112588
|
+
const absoluteTarget = isAbsolute4(filePath) ? resolve10(filePath) : resolve10(root, filePath);
|
|
112589
|
+
let canonicalRoot = root;
|
|
112590
|
+
try {
|
|
112591
|
+
canonicalRoot = await fs3.realpath(root);
|
|
112592
|
+
} catch {
|
|
112593
|
+
}
|
|
112594
|
+
const canonicalTarget = await canonicalizeMaybeMissing(fs3, absoluteTarget);
|
|
112595
|
+
let targetStat = null;
|
|
112596
|
+
try {
|
|
112597
|
+
targetStat = await fs3.stat(canonicalTarget, { followSymlinks: true });
|
|
112598
|
+
} catch {
|
|
112599
|
+
}
|
|
112600
|
+
const normalizedRoot = canonicalRoot.replace(/\/+$/, "");
|
|
112601
|
+
const inside = canonicalTarget === normalizedRoot || canonicalTarget.startsWith(`${normalizedRoot}${sep6}`);
|
|
112602
|
+
const relativePath = inside ? (canonicalTarget === normalizedRoot ? "" : canonicalTarget.slice(normalizedRoot.length + 1)).split(sep6).join("/") : null;
|
|
112603
|
+
return {
|
|
112604
|
+
canonicalTarget,
|
|
112605
|
+
exists: !!targetStat,
|
|
112606
|
+
isFile: targetStat?.kind === "file",
|
|
112607
|
+
inside,
|
|
112608
|
+
relativePath
|
|
112609
|
+
};
|
|
112610
|
+
}
|
|
112611
|
+
async function canonicalizeMaybeMissing(fs3, p2) {
|
|
112612
|
+
try {
|
|
112613
|
+
return await fs3.realpath(p2);
|
|
112614
|
+
} catch {
|
|
112615
|
+
}
|
|
112616
|
+
const parts = p2.split(sep6);
|
|
112617
|
+
for (let i = parts.length - 1; i > 0; i--) {
|
|
112618
|
+
const prefix = parts.slice(0, i).join(sep6) || sep6;
|
|
112619
|
+
try {
|
|
112620
|
+
const canonicalPrefix = await fs3.realpath(prefix);
|
|
112621
|
+
return join51(canonicalPrefix, ...parts.slice(i));
|
|
112622
|
+
} catch {
|
|
112623
|
+
}
|
|
112624
|
+
}
|
|
112625
|
+
return p2;
|
|
112626
|
+
}
|
|
112627
|
+
|
|
112527
112628
|
// src/server/services/editor-service.ts
|
|
112528
112629
|
init_errors6();
|
|
112529
112630
|
init_registry();
|
|
112530
112631
|
|
|
112531
|
-
//
|
|
112532
|
-
init_worktree_service();
|
|
112632
|
+
// ../../packages/worktree-ops/src/file-watch.ts
|
|
112533
112633
|
var IGNORED_SEGMENTS = /* @__PURE__ */ new Set([
|
|
112534
112634
|
".git",
|
|
112535
112635
|
"node_modules",
|
|
@@ -112600,16 +112700,15 @@ async function pumpChanges(worktreeId4, entry, host, root) {
|
|
|
112600
112700
|
for (const listener of entry.listeners) listener(null);
|
|
112601
112701
|
stopWatcher(worktreeId4, entry);
|
|
112602
112702
|
}
|
|
112603
|
-
function subscribeToFileChanges(worktreeId4, listener) {
|
|
112703
|
+
function subscribeToFileChanges(worktreeId4, open4, listener) {
|
|
112604
112704
|
let entry = watchers.get(worktreeId4);
|
|
112605
112705
|
if (!entry) {
|
|
112606
|
-
const
|
|
112607
|
-
if (!
|
|
112706
|
+
const target = open4();
|
|
112707
|
+
if (!target) return () => {
|
|
112608
112708
|
};
|
|
112609
|
-
const root = ws.worktree.path;
|
|
112610
112709
|
entry = { controller: new AbortController(), listeners: /* @__PURE__ */ new Set(), pendingTimers: /* @__PURE__ */ new Map() };
|
|
112611
112710
|
watchers.set(worktreeId4, entry);
|
|
112612
|
-
void pumpChanges(worktreeId4, entry,
|
|
112711
|
+
void pumpChanges(worktreeId4, entry, target.host, target.root);
|
|
112613
112712
|
}
|
|
112614
112713
|
entry.listeners.add(listener);
|
|
112615
112714
|
const subscribed = entry;
|
|
@@ -112619,10 +112718,23 @@ function subscribeToFileChanges(worktreeId4, listener) {
|
|
|
112619
112718
|
};
|
|
112620
112719
|
}
|
|
112621
112720
|
|
|
112721
|
+
// src/server/services/file-watcher.ts
|
|
112722
|
+
init_worktree_service();
|
|
112723
|
+
function subscribeToFileChanges2(worktreeId4, listener) {
|
|
112724
|
+
return subscribeToFileChanges(
|
|
112725
|
+
worktreeId4,
|
|
112726
|
+
() => {
|
|
112727
|
+
const ws = worktreeService.resolve(worktreeId4);
|
|
112728
|
+
return ws ? { host: ws.host, root: ws.worktree.path } : null;
|
|
112729
|
+
},
|
|
112730
|
+
listener
|
|
112731
|
+
);
|
|
112732
|
+
}
|
|
112733
|
+
|
|
112622
112734
|
// src/server/services/formatter.ts
|
|
112623
112735
|
init_src();
|
|
112624
112736
|
init_registry();
|
|
112625
|
-
import { basename as basename4, dirname as dirname15, isAbsolute as
|
|
112737
|
+
import { basename as basename4, dirname as dirname15, isAbsolute as isAbsolute5, join as join52, resolve as resolvePath3 } from "node:path";
|
|
112626
112738
|
import prettier from "prettier";
|
|
112627
112739
|
var log64 = createLogger("formatter");
|
|
112628
112740
|
var FormatterError = class extends Error {
|
|
@@ -112638,7 +112750,7 @@ var FormatterError = class extends Error {
|
|
|
112638
112750
|
async function formatFile(worktreePath, filePath, content, options = {}) {
|
|
112639
112751
|
const fs3 = options.fs ?? hostRegistry.local.fs;
|
|
112640
112752
|
const onHub = fs3 === hostRegistry.local.fs;
|
|
112641
|
-
const absFile =
|
|
112753
|
+
const absFile = isAbsolute5(filePath) ? filePath : resolvePath3(worktreePath, filePath);
|
|
112642
112754
|
if (!await isInsideWorktree(fs3, absFile, worktreePath)) {
|
|
112643
112755
|
throw new FormatterError(
|
|
112644
112756
|
"FILE_NOT_IN_WORKTREE",
|
|
@@ -112704,10 +112816,10 @@ async function resolveConfigOnHost(fs3, absFile, worktreePath) {
|
|
|
112704
112816
|
let dir = dirname15(absFile);
|
|
112705
112817
|
for (; ; ) {
|
|
112706
112818
|
for (const name5 of JSON_CONFIGS) {
|
|
112707
|
-
const parsed = await readJson2(fs3,
|
|
112819
|
+
const parsed = await readJson2(fs3, join52(dir, name5));
|
|
112708
112820
|
if (parsed && typeof parsed === "object") return withoutPlugins(parsed);
|
|
112709
112821
|
}
|
|
112710
|
-
const pkg = await readJson2(fs3,
|
|
112822
|
+
const pkg = await readJson2(fs3, join52(dir, "package.json"));
|
|
112711
112823
|
if (pkg && typeof pkg.prettier === "object" && pkg.prettier !== null) {
|
|
112712
112824
|
return withoutPlugins(pkg.prettier);
|
|
112713
112825
|
}
|
|
@@ -112745,7 +112857,7 @@ async function isInsideWorktree(fs3, absFile, worktreePath) {
|
|
|
112745
112857
|
realFile = await fs3.realpath(absFile);
|
|
112746
112858
|
} catch {
|
|
112747
112859
|
try {
|
|
112748
|
-
realFile =
|
|
112860
|
+
realFile = join52(await fs3.realpath(dirname15(absFile)), basename4(absFile));
|
|
112749
112861
|
} catch {
|
|
112750
112862
|
realFile = absFile;
|
|
112751
112863
|
}
|
|
@@ -112796,7 +112908,7 @@ var EditorService = class {
|
|
|
112796
112908
|
// File-change subscriptions (per-worktree fs.watch)
|
|
112797
112909
|
// -------------------------------------------------------------------------
|
|
112798
112910
|
subscribeToFileChanges(worktreeId4, listener) {
|
|
112799
|
-
return
|
|
112911
|
+
return subscribeToFileChanges2(worktreeId4, listener);
|
|
112800
112912
|
}
|
|
112801
112913
|
// -------------------------------------------------------------------------
|
|
112802
112914
|
// LSP lifecycle pass-throughs
|
|
@@ -112823,11 +112935,7 @@ var EditorService = class {
|
|
|
112823
112935
|
if (!worktree) {
|
|
112824
112936
|
throw new EditorOpenError("NOT_FOUND", `Worktree '${targetWorktreeId}' not found`);
|
|
112825
112937
|
}
|
|
112826
|
-
const resolved = await
|
|
112827
|
-
worktree.host.fs,
|
|
112828
|
-
worktree.worktree.path,
|
|
112829
|
-
input3.filePath
|
|
112830
|
-
);
|
|
112938
|
+
const resolved = await resolveTarget(worktree.host.fs, worktree.worktree.path, input3.filePath);
|
|
112831
112939
|
if (!resolved.exists) {
|
|
112832
112940
|
throw new EditorOpenError("NOT_FOUND", `File not found: ${input3.filePath}`);
|
|
112833
112941
|
}
|
|
@@ -112853,66 +112961,6 @@ var EditorService = class {
|
|
|
112853
112961
|
external: !resolved.inside
|
|
112854
112962
|
};
|
|
112855
112963
|
}
|
|
112856
|
-
/**
|
|
112857
|
-
* Resolve a path (absolute or worktree-relative) against a worktree and
|
|
112858
|
-
* report where it lands. Used by the dashboard's Quick Open to decide, for
|
|
112859
|
-
* an absolute-path query, whether to open the file as a normal
|
|
112860
|
-
* worktree-relative tab (when it lives *inside* the worktree) or as an
|
|
112861
|
-
* external tab (outside) — and, either way, whether it exists at all.
|
|
112862
|
-
*
|
|
112863
|
-
* Shares the exact canonicalize + segment-aware containment logic that
|
|
112864
|
-
* `openFile` uses, so an absolute path typed into Quick Open and the same
|
|
112865
|
-
* path passed to `band open` resolve identically. Unlike `openFile` this
|
|
112866
|
-
* neither emits an SSE event nor throws for a missing file — the caller
|
|
112867
|
-
* only offers to open when `exists && isFile`.
|
|
112868
|
-
*/
|
|
112869
|
-
async resolvePath(input3) {
|
|
112870
|
-
const worktree = worktreeService.resolve(input3.worktreeId);
|
|
112871
|
-
if (!worktree) {
|
|
112872
|
-
throw new WorktreeNotFoundError(input3.worktreeId);
|
|
112873
|
-
}
|
|
112874
|
-
const resolved = await this.resolveTarget(
|
|
112875
|
-
worktree.host.fs,
|
|
112876
|
-
worktree.worktree.path,
|
|
112877
|
-
input3.filePath
|
|
112878
|
-
);
|
|
112879
|
-
return {
|
|
112880
|
-
exists: resolved.exists,
|
|
112881
|
-
isFile: resolved.isFile,
|
|
112882
|
-
external: !resolved.inside,
|
|
112883
|
-
worktreeRelativePath: resolved.inside ? resolved.relativePath : null
|
|
112884
|
-
};
|
|
112885
|
-
}
|
|
112886
|
-
/**
|
|
112887
|
-
* Shared resolution core for {@link openFile} and {@link resolvePath}:
|
|
112888
|
-
* canonicalize the target (following the deepest existing ancestor so
|
|
112889
|
-
* not-yet-created paths still classify), stat it, and run the
|
|
112890
|
-
* segment-aware containment check against the canonicalized worktree root.
|
|
112891
|
-
*/
|
|
112892
|
-
async resolveTarget(fs3, root, filePath) {
|
|
112893
|
-
const absoluteTarget = isAbsolute5(filePath) ? resolve10(filePath) : resolve10(root, filePath);
|
|
112894
|
-
let canonicalRoot = root;
|
|
112895
|
-
try {
|
|
112896
|
-
canonicalRoot = await fs3.realpath(root);
|
|
112897
|
-
} catch {
|
|
112898
|
-
}
|
|
112899
|
-
const canonicalTarget = await canonicalizeMaybeMissing(fs3, absoluteTarget);
|
|
112900
|
-
let targetStat = null;
|
|
112901
|
-
try {
|
|
112902
|
-
targetStat = await fs3.stat(canonicalTarget, { followSymlinks: true });
|
|
112903
|
-
} catch {
|
|
112904
|
-
}
|
|
112905
|
-
const normalizedRoot = canonicalRoot.replace(/\/+$/, "");
|
|
112906
|
-
const inside = canonicalTarget === normalizedRoot || canonicalTarget.startsWith(`${normalizedRoot}${sep6}`);
|
|
112907
|
-
const relativePath = inside ? (canonicalTarget === normalizedRoot ? "" : canonicalTarget.slice(normalizedRoot.length + 1)).split(sep6).join("/") : null;
|
|
112908
|
-
return {
|
|
112909
|
-
canonicalTarget,
|
|
112910
|
-
exists: !!targetStat,
|
|
112911
|
-
isFile: targetStat?.kind === "file",
|
|
112912
|
-
inside,
|
|
112913
|
-
relativePath
|
|
112914
|
-
};
|
|
112915
|
-
}
|
|
112916
112964
|
};
|
|
112917
112965
|
var EditorOpenError = class extends Error {
|
|
112918
112966
|
code;
|
|
@@ -112922,22 +112970,6 @@ var EditorOpenError = class extends Error {
|
|
|
112922
112970
|
this.code = code;
|
|
112923
112971
|
}
|
|
112924
112972
|
};
|
|
112925
|
-
async function canonicalizeMaybeMissing(fs3, p2) {
|
|
112926
|
-
try {
|
|
112927
|
-
return await fs3.realpath(p2);
|
|
112928
|
-
} catch {
|
|
112929
|
-
}
|
|
112930
|
-
const parts = p2.split(sep6);
|
|
112931
|
-
for (let i = parts.length - 1; i > 0; i--) {
|
|
112932
|
-
const prefix = parts.slice(0, i).join(sep6) || sep6;
|
|
112933
|
-
try {
|
|
112934
|
-
const canonicalPrefix = await fs3.realpath(prefix);
|
|
112935
|
-
return join52(canonicalPrefix, ...parts.slice(i));
|
|
112936
|
-
} catch {
|
|
112937
|
-
}
|
|
112938
|
-
}
|
|
112939
|
-
return p2;
|
|
112940
|
-
}
|
|
112941
112973
|
var editorService = new EditorService();
|
|
112942
112974
|
|
|
112943
112975
|
// src/server/api/editor/router.ts
|
|
@@ -113700,7 +113732,7 @@ init_registry();
|
|
|
113700
113732
|
// package.json
|
|
113701
113733
|
var package_default = {
|
|
113702
113734
|
name: "@band-app/server",
|
|
113703
|
-
version: "0.
|
|
113735
|
+
version: "0.56.0",
|
|
113704
113736
|
type: "module",
|
|
113705
113737
|
types: "src/index.ts",
|
|
113706
113738
|
exports: {
|
|
@@ -118504,11 +118536,11 @@ var ProvisionQueries = class {
|
|
|
118504
118536
|
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();
|
|
118505
118537
|
return Number(result.changes ?? 0) > 0;
|
|
118506
118538
|
}
|
|
118507
|
-
setLog(id,
|
|
118508
|
-
this.db().update(hostProvisions).set({ log:
|
|
118539
|
+
setLog(id, log95, at) {
|
|
118540
|
+
this.db().update(hostProvisions).set({ log: log95, updatedAt: at }).where(eq2(hostProvisions.id, id)).run();
|
|
118509
118541
|
}
|
|
118510
|
-
finish(id, state2, exitCode,
|
|
118511
|
-
this.db().update(hostProvisions).set({ state: state2, exitCode, log:
|
|
118542
|
+
finish(id, state2, exitCode, log95, at) {
|
|
118543
|
+
this.db().update(hostProvisions).set({ state: state2, exitCode, log: log95, updatedAt: at }).where(eq2(hostProvisions.id, id)).run();
|
|
118512
118544
|
}
|
|
118513
118545
|
/** Ids of rows created before `at`, so their bundle files can be deleted. */
|
|
118514
118546
|
idsCreatedBefore(at) {
|
|
@@ -122098,6 +122130,32 @@ var searchContentInput = external_exports2.object({
|
|
|
122098
122130
|
regex: external_exports2.boolean().default(false),
|
|
122099
122131
|
limit: external_exports2.number().default(100)
|
|
122100
122132
|
});
|
|
122133
|
+
var commitShaSchema = external_exports2.string().regex(/^[0-9a-f]{7,40}$/i, "sha must be a 7\u201340 character hex commit id");
|
|
122134
|
+
var listBranchesInput = external_exports2.object({
|
|
122135
|
+
worktreeId: external_exports2.string(),
|
|
122136
|
+
query: external_exports2.string().max(200).optional(),
|
|
122137
|
+
limit: external_exports2.number().int().min(1).max(500).optional()
|
|
122138
|
+
});
|
|
122139
|
+
var getCommitHistoryInput = external_exports2.object({
|
|
122140
|
+
worktreeId: external_exports2.string(),
|
|
122141
|
+
skip: external_exports2.number().int().min(0).optional(),
|
|
122142
|
+
limit: external_exports2.number().int().min(1).max(500).optional()
|
|
122143
|
+
});
|
|
122144
|
+
var getCommitHistorySignatureInput = external_exports2.object({ worktreeId: external_exports2.string() });
|
|
122145
|
+
var getCommitDetailsInput = external_exports2.object({ worktreeId: external_exports2.string(), sha: commitShaSchema });
|
|
122146
|
+
var createFileInput = external_exports2.object({
|
|
122147
|
+
worktreeId: external_exports2.string(),
|
|
122148
|
+
path: external_exports2.string().min(1),
|
|
122149
|
+
content: external_exports2.string().default("")
|
|
122150
|
+
});
|
|
122151
|
+
var createDirectoryInput = external_exports2.object({ worktreeId: external_exports2.string(), path: external_exports2.string().min(1) });
|
|
122152
|
+
var deletePathInput = external_exports2.object({ worktreeId: external_exports2.string(), path: external_exports2.string().min(1) });
|
|
122153
|
+
var renamePathInput = external_exports2.object({
|
|
122154
|
+
worktreeId: external_exports2.string(),
|
|
122155
|
+
fromPath: external_exports2.string().min(1),
|
|
122156
|
+
toPath: external_exports2.string().min(1)
|
|
122157
|
+
});
|
|
122158
|
+
var resolvePathInput = external_exports2.object({ worktreeId: external_exports2.string(), path: external_exports2.string().min(1) });
|
|
122101
122159
|
|
|
122102
122160
|
// ../../packages/worktree-ops/src/direct.ts
|
|
122103
122161
|
var op = (o) => o;
|
|
@@ -122149,6 +122207,42 @@ var directOps = {
|
|
|
122149
122207
|
regex: i.regex,
|
|
122150
122208
|
limit: i.limit
|
|
122151
122209
|
})
|
|
122210
|
+
}),
|
|
122211
|
+
"worktree.listBranches": op({
|
|
122212
|
+
input: listBranchesInput,
|
|
122213
|
+
run: (ops, i) => ops.diff.listBranches(i.worktreeId, { query: i.query, limit: i.limit })
|
|
122214
|
+
}),
|
|
122215
|
+
"worktree.getCommitHistory": op({
|
|
122216
|
+
input: getCommitHistoryInput,
|
|
122217
|
+
run: (ops, i) => ops.gitGraph.getCommitHistory(i.worktreeId, { skip: i.skip, limit: i.limit })
|
|
122218
|
+
}),
|
|
122219
|
+
"worktree.getCommitHistorySignature": op({
|
|
122220
|
+
input: getCommitHistorySignatureInput,
|
|
122221
|
+
run: (ops, i) => ops.gitGraph.getCommitHistorySignature(i.worktreeId)
|
|
122222
|
+
}),
|
|
122223
|
+
"worktree.getCommitDetails": op({
|
|
122224
|
+
input: getCommitDetailsInput,
|
|
122225
|
+
run: (ops, i) => ops.gitGraph.getCommitDetails(i.worktreeId, i.sha)
|
|
122226
|
+
}),
|
|
122227
|
+
"worktree.createFile": op({
|
|
122228
|
+
input: createFileInput,
|
|
122229
|
+
run: (ops, i) => ops.files.createFile(i.worktreeId, i.path, i.content)
|
|
122230
|
+
}),
|
|
122231
|
+
"worktree.createDirectory": op({
|
|
122232
|
+
input: createDirectoryInput,
|
|
122233
|
+
run: (ops, i) => ops.files.createDirectory(i.worktreeId, i.path)
|
|
122234
|
+
}),
|
|
122235
|
+
"worktree.deletePath": op({
|
|
122236
|
+
input: deletePathInput,
|
|
122237
|
+
run: (ops, i) => ops.files.deletePath(i.worktreeId, i.path)
|
|
122238
|
+
}),
|
|
122239
|
+
"worktree.renamePath": op({
|
|
122240
|
+
input: renamePathInput,
|
|
122241
|
+
run: (ops, i) => ops.files.renamePath(i.worktreeId, i.fromPath, i.toPath)
|
|
122242
|
+
}),
|
|
122243
|
+
"worktree.copyPath": op({
|
|
122244
|
+
input: renamePathInput,
|
|
122245
|
+
run: (ops, i) => ops.files.copyPath(i.worktreeId, i.fromPath, i.toPath)
|
|
122152
122246
|
})
|
|
122153
122247
|
};
|
|
122154
122248
|
|
|
@@ -123146,11 +123240,10 @@ var filesService = new FilesService({
|
|
|
123146
123240
|
ensureAwake: (worktreeId4) => ephemeralLifecycleService.ensureAwake(worktreeId4)
|
|
123147
123241
|
});
|
|
123148
123242
|
|
|
123149
|
-
//
|
|
123243
|
+
// ../../packages/worktree-ops/src/git-graph.ts
|
|
123150
123244
|
init_src3();
|
|
123151
123245
|
import { createHash as createHash14 } from "node:crypto";
|
|
123152
|
-
|
|
123153
|
-
init_worktree_service();
|
|
123246
|
+
init_resolver();
|
|
123154
123247
|
var FS = "";
|
|
123155
123248
|
var RS = "";
|
|
123156
123249
|
var COMMIT_HISTORY_DEFAULT_LIMIT = 50;
|
|
@@ -123196,7 +123289,7 @@ function parseNameStatus2(output2) {
|
|
|
123196
123289
|
return files;
|
|
123197
123290
|
}
|
|
123198
123291
|
var GitGraphService = class {
|
|
123199
|
-
constructor(worktrees2
|
|
123292
|
+
constructor(worktrees2) {
|
|
123200
123293
|
this.worktrees = worktrees2;
|
|
123201
123294
|
}
|
|
123202
123295
|
target(worktreeId4) {
|
|
@@ -123325,7 +123418,10 @@ var GitGraphService = class {
|
|
|
123325
123418
|
return { diff };
|
|
123326
123419
|
}
|
|
123327
123420
|
};
|
|
123328
|
-
|
|
123421
|
+
|
|
123422
|
+
// src/server/services/git-graph-service.ts
|
|
123423
|
+
init_worktree_service();
|
|
123424
|
+
var gitGraphService = new GitGraphService(worktreeService);
|
|
123329
123425
|
|
|
123330
123426
|
// ../../node_modules/.pnpm/fzf@0.5.2/node_modules/fzf/dist/fzf.es.js
|
|
123331
123427
|
var normalized = {
|
|
@@ -124383,9 +124479,14 @@ var searchService = new SearchService({
|
|
|
124383
124479
|
// src/server/api/worktree/router.ts
|
|
124384
124480
|
init_terminal_service();
|
|
124385
124481
|
init_worktree_service();
|
|
124386
|
-
var
|
|
124482
|
+
var pathsService = new PathsService(worktreeService);
|
|
124483
|
+
var worktreeOps = {
|
|
124484
|
+
files: filesService,
|
|
124485
|
+
diff: diffService,
|
|
124486
|
+
search: searchService,
|
|
124487
|
+
gitGraph: gitGraphService
|
|
124488
|
+
};
|
|
124387
124489
|
var pathListSchema = external_exports2.array(filePathSchema).min(1).max(5e4);
|
|
124388
|
-
var commitShaSchema = external_exports2.string().regex(/^[0-9a-f]{7,40}$/i, "sha must be a 7\u201340 character hex commit id");
|
|
124389
124490
|
var worktreeRouter = t.router({
|
|
124390
124491
|
/**
|
|
124391
124492
|
* A short-lived token for the worker that holds `worktreeId`, when that
|
|
@@ -124493,29 +124594,10 @@ var worktreeRouter = t.router({
|
|
|
124493
124594
|
unsubscribe();
|
|
124494
124595
|
}
|
|
124495
124596
|
}),
|
|
124496
|
-
listBranches: publicProcedure.input(
|
|
124497
|
-
|
|
124498
|
-
|
|
124499
|
-
|
|
124500
|
-
limit: external_exports2.number().int().min(1).max(500).optional()
|
|
124501
|
-
})
|
|
124502
|
-
).query(
|
|
124503
|
-
({ input: input3 }) => diffService.listBranches(input3.worktreeId, { query: input3.query, limit: input3.limit })
|
|
124504
|
-
),
|
|
124505
|
-
getCommitHistory: publicProcedure.input(
|
|
124506
|
-
external_exports2.object({
|
|
124507
|
-
worktreeId: external_exports2.string(),
|
|
124508
|
-
skip: external_exports2.number().int().min(0).optional(),
|
|
124509
|
-
limit: external_exports2.number().int().min(1).max(500).optional()
|
|
124510
|
-
})
|
|
124511
|
-
).query(
|
|
124512
|
-
({ input: input3 }) => gitGraphService.getCommitHistory(input3.worktreeId, {
|
|
124513
|
-
skip: input3.skip,
|
|
124514
|
-
limit: input3.limit
|
|
124515
|
-
})
|
|
124516
|
-
),
|
|
124517
|
-
getCommitHistorySignature: publicProcedure.input(external_exports2.object({ worktreeId: external_exports2.string() })).query(({ input: input3 }) => gitGraphService.getCommitHistorySignature(input3.worktreeId)),
|
|
124518
|
-
getCommitDetails: publicProcedure.input(external_exports2.object({ worktreeId: external_exports2.string(), sha: commitShaSchema })).query(({ input: input3 }) => gitGraphService.getCommitDetails(input3.worktreeId, input3.sha)),
|
|
124597
|
+
listBranches: publicProcedure.input(directOps["worktree.listBranches"].input).query(({ input: input3 }) => directOps["worktree.listBranches"].run(worktreeOps, input3)),
|
|
124598
|
+
getCommitHistory: publicProcedure.input(directOps["worktree.getCommitHistory"].input).query(({ input: input3 }) => directOps["worktree.getCommitHistory"].run(worktreeOps, input3)),
|
|
124599
|
+
getCommitHistorySignature: publicProcedure.input(directOps["worktree.getCommitHistorySignature"].input).query(({ input: input3 }) => directOps["worktree.getCommitHistorySignature"].run(worktreeOps, input3)),
|
|
124600
|
+
getCommitDetails: publicProcedure.input(directOps["worktree.getCommitDetails"].input).query(({ input: input3 }) => directOps["worktree.getCommitDetails"].run(worktreeOps, input3)),
|
|
124519
124601
|
getCommitFileDiff: publicProcedure.input(
|
|
124520
124602
|
external_exports2.object({
|
|
124521
124603
|
worktreeId: external_exports2.string(),
|
|
@@ -124563,31 +124645,11 @@ var worktreeRouter = t.router({
|
|
|
124563
124645
|
listFiles: publicProcedure.input(directOps["worktree.listFiles"].input).query(({ input: input3 }) => directOps["worktree.listFiles"].run(worktreeOps, input3)),
|
|
124564
124646
|
getFile: publicProcedure.input(directOps["worktree.getFile"].input).query(({ input: input3 }) => directOps["worktree.getFile"].run(worktreeOps, input3)),
|
|
124565
124647
|
saveFile: publicProcedure.input(directOps["worktree.saveFile"].input).mutation(({ input: input3 }) => directOps["worktree.saveFile"].run(worktreeOps, input3)),
|
|
124566
|
-
createFile: publicProcedure.input(
|
|
124567
|
-
|
|
124568
|
-
|
|
124569
|
-
|
|
124570
|
-
|
|
124571
|
-
})
|
|
124572
|
-
).mutation(({ input: input3 }) => filesService.createFile(input3.worktreeId, input3.path, input3.content)),
|
|
124573
|
-
createDirectory: publicProcedure.input(external_exports2.object({ worktreeId: external_exports2.string(), path: external_exports2.string().min(1) })).mutation(({ input: input3 }) => filesService.createDirectory(input3.worktreeId, input3.path)),
|
|
124574
|
-
deletePath: publicProcedure.input(external_exports2.object({ worktreeId: external_exports2.string(), path: external_exports2.string().min(1) })).mutation(({ input: input3 }) => filesService.deletePath(input3.worktreeId, input3.path)),
|
|
124575
|
-
renamePath: publicProcedure.input(
|
|
124576
|
-
external_exports2.object({
|
|
124577
|
-
worktreeId: external_exports2.string(),
|
|
124578
|
-
fromPath: external_exports2.string().min(1),
|
|
124579
|
-
toPath: external_exports2.string().min(1)
|
|
124580
|
-
})
|
|
124581
|
-
).mutation(
|
|
124582
|
-
({ input: input3 }) => filesService.renamePath(input3.worktreeId, input3.fromPath, input3.toPath)
|
|
124583
|
-
),
|
|
124584
|
-
copyPath: publicProcedure.input(
|
|
124585
|
-
external_exports2.object({
|
|
124586
|
-
worktreeId: external_exports2.string(),
|
|
124587
|
-
fromPath: external_exports2.string().min(1),
|
|
124588
|
-
toPath: external_exports2.string().min(1)
|
|
124589
|
-
})
|
|
124590
|
-
).mutation(({ input: input3 }) => filesService.copyPath(input3.worktreeId, input3.fromPath, input3.toPath)),
|
|
124648
|
+
createFile: publicProcedure.input(directOps["worktree.createFile"].input).mutation(({ input: input3 }) => directOps["worktree.createFile"].run(worktreeOps, input3)),
|
|
124649
|
+
createDirectory: publicProcedure.input(directOps["worktree.createDirectory"].input).mutation(({ input: input3 }) => directOps["worktree.createDirectory"].run(worktreeOps, input3)),
|
|
124650
|
+
deletePath: publicProcedure.input(directOps["worktree.deletePath"].input).mutation(({ input: input3 }) => directOps["worktree.deletePath"].run(worktreeOps, input3)),
|
|
124651
|
+
renamePath: publicProcedure.input(directOps["worktree.renamePath"].input).mutation(({ input: input3 }) => directOps["worktree.renamePath"].run(worktreeOps, input3)),
|
|
124652
|
+
copyPath: publicProcedure.input(directOps["worktree.copyPath"].input).mutation(({ input: input3 }) => directOps["worktree.copyPath"].run(worktreeOps, input3)),
|
|
124591
124653
|
/** A signed, expiring URL for one worktree file, for a browser tab that cannot send the auth header. */
|
|
124592
124654
|
previewUrl: publicProcedure.input(external_exports2.object({ worktreeId: external_exports2.string(), path: external_exports2.string().min(1) })).query(({ input: input3 }) => {
|
|
124593
124655
|
if (!worktreeService.resolve(input3.worktreeId)) {
|
|
@@ -124610,8 +124672,8 @@ var worktreeRouter = t.router({
|
|
|
124610
124672
|
// `host.readFile` — and the `external` flag is load-bearing, not dead code:
|
|
124611
124673
|
// it's how the client decides between a worktree-relative and an external
|
|
124612
124674
|
// tab. Do not "harden" this by dropping the out-of-worktree classification.
|
|
124613
|
-
resolvePath: publicProcedure.input(
|
|
124614
|
-
({ input: input3 }) =>
|
|
124675
|
+
resolvePath: publicProcedure.input(resolvePathInput).query(
|
|
124676
|
+
({ input: input3 }) => pathsService.resolvePath({ worktreeId: input3.worktreeId, filePath: input3.path })
|
|
124615
124677
|
),
|
|
124616
124678
|
searchContent: publicProcedure.input(directOps["worktree.searchContent"].input).query(({ input: input3 }) => directOps["worktree.searchContent"].run(worktreeOps, input3))
|
|
124617
124679
|
});
|
|
@@ -125847,18 +125909,11 @@ async function handlePairExchange(req, res) {
|
|
|
125847
125909
|
|
|
125848
125910
|
// src/server/api/plugins/stream-handler.ts
|
|
125849
125911
|
init_src();
|
|
125850
|
-
|
|
125912
|
+
|
|
125913
|
+
// ../../packages/worktree-ops/src/plugin-stream-socket.ts
|
|
125914
|
+
init_src();
|
|
125851
125915
|
var log85 = createLogger("plugin-stream");
|
|
125852
|
-
var
|
|
125853
|
-
function pluginStreamTarget(pathname) {
|
|
125854
|
-
const match = STREAM_PATH.exec(pathname);
|
|
125855
|
-
if (!match?.[1] || !match[2]) return null;
|
|
125856
|
-
try {
|
|
125857
|
-
return { pluginId: match[1], worktreeId: decodeURIComponent(match[2]) };
|
|
125858
|
-
} catch {
|
|
125859
|
-
return null;
|
|
125860
|
-
}
|
|
125861
|
-
}
|
|
125916
|
+
var MAX_INPUT_BYTES = 64 * 1024;
|
|
125862
125917
|
function parseModeRequest(text4) {
|
|
125863
125918
|
try {
|
|
125864
125919
|
const msg = JSON.parse(text4);
|
|
@@ -125867,8 +125922,7 @@ function parseModeRequest(text4) {
|
|
|
125867
125922
|
}
|
|
125868
125923
|
return null;
|
|
125869
125924
|
}
|
|
125870
|
-
|
|
125871
|
-
async function handlePluginStream(ws, req, target) {
|
|
125925
|
+
async function bridgePluginStream(ws, label2, open4, onOpenFailed) {
|
|
125872
125926
|
let controlling = false;
|
|
125873
125927
|
let stream = null;
|
|
125874
125928
|
ws.on("message", (data, isBinary) => {
|
|
@@ -125879,35 +125933,24 @@ async function handlePluginStream(ws, req, target) {
|
|
|
125879
125933
|
const enabled = parseModeRequest(text4);
|
|
125880
125934
|
if (enabled !== null) {
|
|
125881
125935
|
controlling = enabled;
|
|
125882
|
-
log85.debug(
|
|
125883
|
-
"%s stream of %s is now %s",
|
|
125884
|
-
target.pluginId,
|
|
125885
|
-
target.worktreeId,
|
|
125886
|
-
enabled ? "controlled" : "view-only"
|
|
125887
|
-
);
|
|
125936
|
+
log85.debug("%s is now %s", label2, enabled ? "controlled" : "view-only");
|
|
125888
125937
|
return;
|
|
125889
125938
|
}
|
|
125890
125939
|
if (controlling && stream && text4.length <= MAX_INPUT_BYTES) stream.send(text4);
|
|
125891
125940
|
});
|
|
125892
125941
|
ws.once("close", () => stream?.close());
|
|
125893
125942
|
try {
|
|
125894
|
-
stream = await
|
|
125943
|
+
stream = await open4();
|
|
125895
125944
|
} catch (err) {
|
|
125896
125945
|
const message = err instanceof Error ? err.message : String(err);
|
|
125897
|
-
log85.warn("%s
|
|
125898
|
-
|
|
125946
|
+
log85.warn("%s is unavailable: %s", label2, message);
|
|
125947
|
+
onOpenFailed(message);
|
|
125899
125948
|
return;
|
|
125900
125949
|
}
|
|
125901
125950
|
if (ws.readyState !== ws.OPEN) {
|
|
125902
125951
|
stream.close();
|
|
125903
125952
|
return;
|
|
125904
125953
|
}
|
|
125905
|
-
log85.debug(
|
|
125906
|
-
"%s viewer connected: %s (%s)",
|
|
125907
|
-
target.pluginId,
|
|
125908
|
-
target.worktreeId,
|
|
125909
|
-
req.socket.remoteAddress ?? "unknown"
|
|
125910
|
-
);
|
|
125911
125954
|
try {
|
|
125912
125955
|
for await (const message of stream.messages) {
|
|
125913
125956
|
if (ws.readyState !== ws.OPEN) break;
|
|
@@ -125916,22 +125959,45 @@ async function handlePluginStream(ws, req, target) {
|
|
|
125916
125959
|
);
|
|
125917
125960
|
}
|
|
125918
125961
|
} catch (err) {
|
|
125919
|
-
log85.warn(
|
|
125920
|
-
"%s stream of %s failed: %s",
|
|
125921
|
-
target.pluginId,
|
|
125922
|
-
target.worktreeId,
|
|
125923
|
-
err.message
|
|
125924
|
-
);
|
|
125962
|
+
log85.warn("%s failed: %s", label2, err.message);
|
|
125925
125963
|
} finally {
|
|
125926
125964
|
stream.close();
|
|
125927
125965
|
if (ws.readyState === ws.OPEN) ws.close(1e3, "The stream ended");
|
|
125928
125966
|
}
|
|
125929
125967
|
}
|
|
125930
125968
|
|
|
125969
|
+
// src/server/api/plugins/stream-handler.ts
|
|
125970
|
+
init_plugin_host_service();
|
|
125971
|
+
var log86 = createLogger("plugin-stream");
|
|
125972
|
+
var STREAM_PATH = /^\/api\/plugins\/([a-z0-9][a-z0-9-]*)\/worktrees\/([^/]+)\/stream$/;
|
|
125973
|
+
function pluginStreamTarget(pathname) {
|
|
125974
|
+
const match = STREAM_PATH.exec(pathname);
|
|
125975
|
+
if (!match?.[1] || !match[2]) return null;
|
|
125976
|
+
try {
|
|
125977
|
+
return { pluginId: match[1], worktreeId: decodeURIComponent(match[2]) };
|
|
125978
|
+
} catch {
|
|
125979
|
+
return null;
|
|
125980
|
+
}
|
|
125981
|
+
}
|
|
125982
|
+
async function handlePluginStream(ws, req, target) {
|
|
125983
|
+
log86.debug(
|
|
125984
|
+
"%s viewer connected: %s (%s)",
|
|
125985
|
+
target.pluginId,
|
|
125986
|
+
target.worktreeId,
|
|
125987
|
+
req.socket.remoteAddress ?? "unknown"
|
|
125988
|
+
);
|
|
125989
|
+
await bridgePluginStream(
|
|
125990
|
+
ws,
|
|
125991
|
+
`${target.pluginId} stream of ${target.worktreeId}`,
|
|
125992
|
+
() => pluginHost.openStream(target.pluginId, target.worktreeId, "screen", { profile: "hub" }),
|
|
125993
|
+
(message) => ws.close(4001, message.slice(0, 120))
|
|
125994
|
+
);
|
|
125995
|
+
}
|
|
125996
|
+
|
|
125931
125997
|
// src/server/api/provisioning/handler.ts
|
|
125932
125998
|
init_src();
|
|
125933
125999
|
import { pipeline } from "node:stream";
|
|
125934
|
-
var
|
|
126000
|
+
var log87 = createLogger("provisioning");
|
|
125935
126001
|
var PROVISION_PREFIX = "/api/provision/";
|
|
125936
126002
|
var MAX_EXCHANGE_BODY_BYTES2 = 4096;
|
|
125937
126003
|
var MAX_LOG_BODY_BYTES = 128 * 1024;
|
|
@@ -125988,7 +126054,7 @@ async function handleProvision(req, res) {
|
|
|
125988
126054
|
send3(200, provisioningService.exchange(code2), "text/plain; charset=utf-8");
|
|
125989
126055
|
} catch (err) {
|
|
125990
126056
|
if (!(err instanceof ProvisionExchangeError)) throw err;
|
|
125991
|
-
|
|
126057
|
+
log87.debug(`provisioning exchange refused: ${err.reason}`);
|
|
125992
126058
|
refused();
|
|
125993
126059
|
}
|
|
125994
126060
|
return;
|
|
@@ -126124,7 +126190,7 @@ var OutputFlow = class {
|
|
|
126124
126190
|
};
|
|
126125
126191
|
|
|
126126
126192
|
// ../../packages/worktree-ops/src/terminal-socket.ts
|
|
126127
|
-
var
|
|
126193
|
+
var log88 = createLogger("terminal-ws");
|
|
126128
126194
|
var MAX_CLOSE_REASON_BYTES = 123;
|
|
126129
126195
|
var HEARTBEAT_INTERVAL_MS2 = 3e4;
|
|
126130
126196
|
function clampCloseReason(reason) {
|
|
@@ -126192,7 +126258,7 @@ function createInbox(ws) {
|
|
|
126192
126258
|
};
|
|
126193
126259
|
}
|
|
126194
126260
|
function attachSession(backend, ws, inbox, terminalId, worktreeId4, isNew, pendingMessage) {
|
|
126195
|
-
|
|
126261
|
+
log88.debug(
|
|
126196
126262
|
"Terminal %s: %s (worktree %s)",
|
|
126197
126263
|
isNew ? "connected" : "reconnected",
|
|
126198
126264
|
terminalId,
|
|
@@ -126212,7 +126278,7 @@ function attachSession(backend, ws, inbox, terminalId, worktreeId4, isNew, pendi
|
|
|
126212
126278
|
});
|
|
126213
126279
|
const unsubscribeExit = backend.onExit(terminalId, (event) => {
|
|
126214
126280
|
unsubscribeTitle();
|
|
126215
|
-
|
|
126281
|
+
log88.debug("PTY exited with code %d for terminal %s", event.exitCode, terminalId);
|
|
126216
126282
|
if (ws.readyState === ws.OPEN) {
|
|
126217
126283
|
ws.close(1e3, "Terminal exited");
|
|
126218
126284
|
}
|
|
@@ -126240,7 +126306,7 @@ function attachSession(backend, ws, inbox, terminalId, worktreeId4, isNew, pendi
|
|
|
126240
126306
|
try {
|
|
126241
126307
|
attached = await backend.attach(terminalId, dims);
|
|
126242
126308
|
} catch (err) {
|
|
126243
|
-
|
|
126309
|
+
log88.error("Failed to attach terminal %s: %s", terminalId, err);
|
|
126244
126310
|
safeClose(ws, 1011, "Terminal attach failed");
|
|
126245
126311
|
return;
|
|
126246
126312
|
}
|
|
@@ -126282,7 +126348,7 @@ function attachSession(backend, ws, inbox, terminalId, worktreeId4, isNew, pendi
|
|
|
126282
126348
|
const cols = Number.isFinite(parsed.cols) && parsed.cols > 0 ? parsed.cols : void 0;
|
|
126283
126349
|
const rows = Number.isFinite(parsed.rows) && parsed.rows > 0 ? parsed.rows : void 0;
|
|
126284
126350
|
void startReplay(cols, rows, parsed.flow === true).catch((err) => {
|
|
126285
|
-
|
|
126351
|
+
log88.error("Failed to replay terminal %s: %s", terminalId, err);
|
|
126286
126352
|
});
|
|
126287
126353
|
return;
|
|
126288
126354
|
}
|
|
@@ -126302,7 +126368,7 @@ function attachSession(backend, ws, inbox, terminalId, worktreeId4, isNew, pendi
|
|
|
126302
126368
|
flow?.dispose();
|
|
126303
126369
|
attachment?.detach();
|
|
126304
126370
|
unsubscribeExit();
|
|
126305
|
-
|
|
126371
|
+
log88.debug("Terminal disconnected: %s (PTY kept alive)", terminalId);
|
|
126306
126372
|
});
|
|
126307
126373
|
if (pendingMessage) {
|
|
126308
126374
|
processMessage(pendingMessage);
|
|
@@ -126325,7 +126391,7 @@ function handleMessage(backend, ws, terminalId, message) {
|
|
|
126325
126391
|
}
|
|
126326
126392
|
if (parsed.type === "close") {
|
|
126327
126393
|
void backend.kill(terminalId).catch((err) => {
|
|
126328
|
-
|
|
126394
|
+
log88.error("Failed to kill terminal %s: %s", terminalId, err);
|
|
126329
126395
|
});
|
|
126330
126396
|
ws.close(1e3, "Terminal closed by client");
|
|
126331
126397
|
return;
|
|
@@ -126341,7 +126407,7 @@ function handleMessage(backend, ws, terminalId, message) {
|
|
|
126341
126407
|
|
|
126342
126408
|
// src/server/api/terminals/ws.ts
|
|
126343
126409
|
init_terminal_service();
|
|
126344
|
-
var
|
|
126410
|
+
var log89 = createLogger("terminal-ws");
|
|
126345
126411
|
async function handleTerminalConnection(ws, req) {
|
|
126346
126412
|
if (!req.url) {
|
|
126347
126413
|
safeClose(ws, 4e3, "Missing request URL");
|
|
@@ -126360,7 +126426,7 @@ async function handleTerminalConnection(ws, req) {
|
|
|
126360
126426
|
existing = await terminalService.info(terminalId) !== null;
|
|
126361
126427
|
} catch (err) {
|
|
126362
126428
|
const msg = err instanceof Error ? err.message : String(err);
|
|
126363
|
-
|
|
126429
|
+
log89.error("Failed to look up terminal %s: %s", terminalId, msg);
|
|
126364
126430
|
safeClose(ws, 1011, msg);
|
|
126365
126431
|
return;
|
|
126366
126432
|
}
|
|
@@ -126408,7 +126474,7 @@ async function handleTerminalConnection(ws, req) {
|
|
|
126408
126474
|
await terminalService.spawn(worktreeId4, terminalId, spawnOpts);
|
|
126409
126475
|
} catch (err) {
|
|
126410
126476
|
const msg = err instanceof Error ? err.message : String(err);
|
|
126411
|
-
|
|
126477
|
+
log89.error("Failed to spawn terminal %s for worktree %s: %s", terminalId, worktreeId4, msg);
|
|
126412
126478
|
safeClose(ws, 4001, msg);
|
|
126413
126479
|
return;
|
|
126414
126480
|
}
|
|
@@ -126547,7 +126613,7 @@ init_src();
|
|
|
126547
126613
|
init_wrapper();
|
|
126548
126614
|
init_browser_lookup();
|
|
126549
126615
|
init_remote_cdp();
|
|
126550
|
-
var
|
|
126616
|
+
var log90 = createLogger("cdp-proxy");
|
|
126551
126617
|
async function handleCdpConnection(ws, req) {
|
|
126552
126618
|
const url3 = new URL(req.url ?? "", `http://${req.headers.host}`);
|
|
126553
126619
|
const bandTabId = url3.searchParams.get("bandTabId");
|
|
@@ -126590,17 +126656,17 @@ async function handleCdpConnection(ws, req) {
|
|
|
126590
126656
|
cdpTargetId = await ensureCdpTargetId(bandTabId);
|
|
126591
126657
|
} catch (err) {
|
|
126592
126658
|
const message = err instanceof Error ? err.message : String(err);
|
|
126593
|
-
|
|
126659
|
+
log90.debug("ensureCdpTargetId failed for %s: %s", bandTabId, message);
|
|
126594
126660
|
if (ws.readyState === ws.OPEN) {
|
|
126595
126661
|
ws.close(4001, message.slice(0, 123));
|
|
126596
126662
|
}
|
|
126597
126663
|
return;
|
|
126598
126664
|
}
|
|
126599
126665
|
const upstreamUrl = `ws://${DESKTOP_CDP_HOST}:${DESKTOP_CDP_PORT}/devtools/page/${encodeURIComponent(cdpTargetId)}`;
|
|
126600
|
-
|
|
126666
|
+
log90.info("CDP proxy connecting bandTabId=%s upstream=%s", bandTabId, upstreamUrl);
|
|
126601
126667
|
upstream = new wrapper_default(upstreamUrl);
|
|
126602
126668
|
upstream.on("open", () => {
|
|
126603
|
-
|
|
126669
|
+
log90.info("CDP upstream open bandTabId=%s pending=%d", bandTabId, pending2.length);
|
|
126604
126670
|
for (const msg of pending2) {
|
|
126605
126671
|
upstream?.send(msg);
|
|
126606
126672
|
}
|
|
@@ -126612,20 +126678,20 @@ async function handleCdpConnection(ws, req) {
|
|
|
126612
126678
|
}
|
|
126613
126679
|
});
|
|
126614
126680
|
upstream.on("error", (err) => {
|
|
126615
|
-
|
|
126681
|
+
log90.warn("CDP upstream error bandTabId=%s: %s", bandTabId, err.message);
|
|
126616
126682
|
markTargetDestroyed(bandTabId);
|
|
126617
126683
|
if (ws.readyState === ws.OPEN) {
|
|
126618
126684
|
ws.close(4001, `Desktop CDP error: ${err.message}`.slice(0, 123));
|
|
126619
126685
|
}
|
|
126620
126686
|
});
|
|
126621
126687
|
upstream.on("close", (code) => {
|
|
126622
|
-
|
|
126688
|
+
log90.info("CDP upstream closed bandTabId=%s code=%d", bandTabId, code);
|
|
126623
126689
|
if (ws.readyState === ws.OPEN) {
|
|
126624
126690
|
ws.close(1e3, "Upstream closed");
|
|
126625
126691
|
}
|
|
126626
126692
|
});
|
|
126627
126693
|
ws.on("close", () => {
|
|
126628
|
-
|
|
126694
|
+
log90.debug("CDP client closed bandTabId=%s", bandTabId);
|
|
126629
126695
|
if (upstream && (upstream.readyState === wrapper_default.OPEN || upstream.readyState === wrapper_default.CONNECTING)) {
|
|
126630
126696
|
try {
|
|
126631
126697
|
upstream.close();
|
|
@@ -126634,7 +126700,7 @@ async function handleCdpConnection(ws, req) {
|
|
|
126634
126700
|
}
|
|
126635
126701
|
});
|
|
126636
126702
|
ws.on("error", (err) => {
|
|
126637
|
-
|
|
126703
|
+
log90.debug("CDP client error bandTabId=%s: %s", bandTabId, err.message);
|
|
126638
126704
|
try {
|
|
126639
126705
|
upstream?.close();
|
|
126640
126706
|
} catch {
|
|
@@ -126664,7 +126730,7 @@ async function bridgeRemote(ws, worktreeId4) {
|
|
|
126664
126730
|
cdp = await openRemoteCdp(worktreeId4);
|
|
126665
126731
|
} catch (err) {
|
|
126666
126732
|
const message = err instanceof Error ? err.message : String(err);
|
|
126667
|
-
|
|
126733
|
+
log90.warn("remote CDP failed for worktree %s: %s", worktreeId4, message);
|
|
126668
126734
|
if (ws.readyState === ws.OPEN)
|
|
126669
126735
|
ws.close(4001, closeReason(`Remote browser unavailable: ${message}`));
|
|
126670
126736
|
return true;
|
|
@@ -126688,7 +126754,7 @@ async function bridgeRemote(ws, worktreeId4) {
|
|
|
126688
126754
|
if (ws.readyState === ws.OPEN) ws.send(message);
|
|
126689
126755
|
}
|
|
126690
126756
|
} catch (err) {
|
|
126691
|
-
|
|
126757
|
+
log90.debug("remote CDP stream ended for worktree %s: %s", worktreeId4, String(err));
|
|
126692
126758
|
}
|
|
126693
126759
|
if (ws.readyState === ws.OPEN) ws.close(1e3, "Upstream closed");
|
|
126694
126760
|
})();
|
|
@@ -126698,7 +126764,7 @@ async function bridgeRemote(ws, worktreeId4) {
|
|
|
126698
126764
|
// src/server/infra/browser-host/cdp-targets.ts
|
|
126699
126765
|
init_src();
|
|
126700
126766
|
init_wrapper();
|
|
126701
|
-
var
|
|
126767
|
+
var log91 = createLogger("cdp-targets");
|
|
126702
126768
|
var CdpUnreachableError = class extends Error {
|
|
126703
126769
|
constructor(message) {
|
|
126704
126770
|
super(message);
|
|
@@ -126754,7 +126820,7 @@ async function captureSnapshot(bandTabId) {
|
|
|
126754
126820
|
});
|
|
126755
126821
|
ws.on("error", (err) => {
|
|
126756
126822
|
clearTimeout(timeout);
|
|
126757
|
-
|
|
126823
|
+
log91.debug("captureSnapshot ws error for tab %s: %s", bandTabId, err.message);
|
|
126758
126824
|
markTargetDestroyed(bandTabId);
|
|
126759
126825
|
settle2(new CdpUnreachableError(err.message));
|
|
126760
126826
|
});
|
|
@@ -126881,7 +126947,7 @@ var RfbClientFilter = class {
|
|
|
126881
126947
|
};
|
|
126882
126948
|
|
|
126883
126949
|
// src/server/infra/host/desktop-proxy.ts
|
|
126884
|
-
var
|
|
126950
|
+
var log92 = createLogger("desktop-proxy");
|
|
126885
126951
|
var DESKTOP_PATH = /^\/api\/hosts\/([^/]+)\/desktop$/;
|
|
126886
126952
|
function desktopHostId(pathname) {
|
|
126887
126953
|
const match = DESKTOP_PATH.exec(pathname);
|
|
@@ -126930,7 +126996,7 @@ async function handleDesktopConnection(ws, req, hostId2) {
|
|
|
126930
126996
|
);
|
|
126931
126997
|
if (enabled !== null) {
|
|
126932
126998
|
filter.viewOnly = !enabled;
|
|
126933
|
-
|
|
126999
|
+
log92.debug("desktop of host %s is now %s", hostId2, enabled ? "controlled" : "view-only");
|
|
126934
127000
|
}
|
|
126935
127001
|
return;
|
|
126936
127002
|
}
|
|
@@ -126965,7 +127031,7 @@ async function handleDesktopConnection(ws, req, hostId2) {
|
|
|
126965
127031
|
opened = true;
|
|
126966
127032
|
} catch (err) {
|
|
126967
127033
|
const message = err instanceof Error ? err.message : String(err);
|
|
126968
|
-
|
|
127034
|
+
log92.warn("desktop of host %s is unavailable: %s", hostId2, message);
|
|
126969
127035
|
release();
|
|
126970
127036
|
ws.close(4001, message.slice(0, 120));
|
|
126971
127037
|
return;
|
|
@@ -126975,7 +127041,7 @@ async function handleDesktopConnection(ws, req, hostId2) {
|
|
|
126975
127041
|
release();
|
|
126976
127042
|
return;
|
|
126977
127043
|
}
|
|
126978
|
-
|
|
127044
|
+
log92.debug("desktop viewer connected: %s (%s)", hostId2, req.socket.remoteAddress ?? "unknown");
|
|
126979
127045
|
for (const chunk of pending2.splice(0)) desktop.write(chunk);
|
|
126980
127046
|
try {
|
|
126981
127047
|
for await (const bytes of desktop.output) {
|
|
@@ -126983,7 +127049,7 @@ async function handleDesktopConnection(ws, req, hostId2) {
|
|
|
126983
127049
|
await new Promise((resolve15) => ws.send(bytes, { binary: true }, () => resolve15()));
|
|
126984
127050
|
}
|
|
126985
127051
|
} catch (err) {
|
|
126986
|
-
|
|
127052
|
+
log92.warn("desktop stream of host %s failed: %s", hostId2, err.message);
|
|
126987
127053
|
} finally {
|
|
126988
127054
|
if (opened) {
|
|
126989
127055
|
desktop.close();
|
|
@@ -126996,12 +127062,9 @@ async function handleDesktopConnection(ws, req, hostId2) {
|
|
|
126996
127062
|
// start-server.ts
|
|
126997
127063
|
init_registry();
|
|
126998
127064
|
|
|
126999
|
-
//
|
|
127065
|
+
// ../../packages/worktree-ops/src/lsp-socket.ts
|
|
127000
127066
|
init_src();
|
|
127001
|
-
|
|
127002
|
-
init_registry();
|
|
127003
|
-
var worktreeQueries2 = new WorktreeQueries();
|
|
127004
|
-
var log92 = createLogger("lsp-proxy");
|
|
127067
|
+
var log93 = createLogger("lsp-proxy");
|
|
127005
127068
|
function frameMessage(json4) {
|
|
127006
127069
|
const body = Buffer.from(json4, "utf-8");
|
|
127007
127070
|
const header = `Content-Length: ${body.byteLength}\r
|
|
@@ -127019,7 +127082,7 @@ function createFrameParser(onMessage) {
|
|
|
127019
127082
|
const headerStr = buffer.subarray(0, separatorIdx).toString("ascii");
|
|
127020
127083
|
const match = headerStr.match(/Content-Length:\s*(\d+)/i);
|
|
127021
127084
|
if (!match) {
|
|
127022
|
-
|
|
127085
|
+
log93.warn("Malformed LSP header: %s", headerStr);
|
|
127023
127086
|
buffer = buffer.subarray(separatorIdx + 4);
|
|
127024
127087
|
continue;
|
|
127025
127088
|
}
|
|
@@ -127043,28 +127106,17 @@ function didCloseMessage(uri) {
|
|
|
127043
127106
|
});
|
|
127044
127107
|
}
|
|
127045
127108
|
var serverDocuments = /* @__PURE__ */ new Map();
|
|
127046
|
-
async function
|
|
127047
|
-
const url3 = new URL(req.url, `http://${req.headers.host}`);
|
|
127048
|
-
const worktreeId4 = url3.searchParams.get("worktreeId");
|
|
127049
|
-
const lang = url3.searchParams.get("lang");
|
|
127050
|
-
if (!worktreeId4 || !lang) {
|
|
127051
|
-
ws.close(4e3, "Missing worktreeId or lang");
|
|
127052
|
-
return;
|
|
127053
|
-
}
|
|
127109
|
+
async function serveLspSocket(ws, worktreeId4, lang, connect3) {
|
|
127054
127110
|
const pendingMessages = [];
|
|
127055
127111
|
ws.on("message", (data) => {
|
|
127056
127112
|
pendingMessages.push(data.toString());
|
|
127057
127113
|
});
|
|
127058
127114
|
let connection;
|
|
127059
127115
|
try {
|
|
127060
|
-
|
|
127061
|
-
if (!worktree) {
|
|
127062
|
-
throw new Error(`Worktree not found: ${worktreeId4}`);
|
|
127063
|
-
}
|
|
127064
|
-
connection = await hostRegistry.hostFor(worktreeId4).lsp.connect({ worktreeId: worktreeId4, lang, root: worktree.worktreePath });
|
|
127116
|
+
connection = await connect3();
|
|
127065
127117
|
} catch (err) {
|
|
127066
127118
|
const message = err instanceof Error ? err.message : String(err);
|
|
127067
|
-
|
|
127119
|
+
log93.error("Failed to spawn %s language server for worktree %s: %s", lang, worktreeId4, message);
|
|
127068
127120
|
ws.close(4001, message);
|
|
127069
127121
|
return;
|
|
127070
127122
|
}
|
|
@@ -127072,7 +127124,7 @@ async function handleLspConnection(ws, req) {
|
|
|
127072
127124
|
connection.close();
|
|
127073
127125
|
return;
|
|
127074
127126
|
}
|
|
127075
|
-
|
|
127127
|
+
log93.debug("LSP client connected: %s/%s", worktreeId4, lang);
|
|
127076
127128
|
const pendingRequests = /* @__PURE__ */ new Map();
|
|
127077
127129
|
const openDocuments = /* @__PURE__ */ new Set();
|
|
127078
127130
|
const serverId = `${worktreeId4}:${lang}`;
|
|
@@ -127108,7 +127160,7 @@ async function handleLspConnection(ws, req) {
|
|
|
127108
127160
|
const retriedIds = /* @__PURE__ */ new Set();
|
|
127109
127161
|
const RETRY_DELAY_MS = 2e3;
|
|
127110
127162
|
const parseFrame = createFrameParser((json4) => {
|
|
127111
|
-
|
|
127163
|
+
log93.debug(
|
|
127112
127164
|
"LSP stdout [%s/%s]: %s",
|
|
127113
127165
|
worktreeId4,
|
|
127114
127166
|
lang,
|
|
@@ -127120,7 +127172,7 @@ async function handleLspConnection(ws, req) {
|
|
|
127120
127172
|
const originalRequest = pendingRequests.get(msg.id);
|
|
127121
127173
|
retriedIds.add(msg.id);
|
|
127122
127174
|
pendingRequests.delete(msg.id);
|
|
127123
|
-
|
|
127175
|
+
log93.debug(
|
|
127124
127176
|
"LSP retrying request %d after 'No Project' error [%s/%s]",
|
|
127125
127177
|
msg.id,
|
|
127126
127178
|
worktreeId4,
|
|
@@ -127151,16 +127203,16 @@ async function handleLspConnection(ws, req) {
|
|
|
127151
127203
|
for await (const chunk of connection.output)
|
|
127152
127204
|
parseFrame(Buffer.from(chunk.buffer, chunk.byteOffset, chunk.byteLength));
|
|
127153
127205
|
} catch (err) {
|
|
127154
|
-
|
|
127206
|
+
log93.warn("LSP output stream failed [%s/%s]: %s", worktreeId4, lang, String(err));
|
|
127155
127207
|
}
|
|
127156
127208
|
release();
|
|
127157
127209
|
if (ws.readyState === ws.OPEN) {
|
|
127158
|
-
|
|
127210
|
+
log93.debug("LSP server exited, closing WebSocket");
|
|
127159
127211
|
ws.close(1e3, "Language server exited");
|
|
127160
127212
|
}
|
|
127161
127213
|
})();
|
|
127162
127214
|
function forwardToStdin(json4) {
|
|
127163
|
-
|
|
127215
|
+
log93.debug(
|
|
127164
127216
|
"LSP stdin [%s/%s]: %s",
|
|
127165
127217
|
worktreeId4,
|
|
127166
127218
|
lang,
|
|
@@ -127192,7 +127244,28 @@ async function handleLspConnection(ws, req) {
|
|
|
127192
127244
|
ws.on("close", () => {
|
|
127193
127245
|
release();
|
|
127194
127246
|
connection.close();
|
|
127195
|
-
|
|
127247
|
+
log93.debug("LSP client disconnected: %s/%s (server kept alive)", worktreeId4, lang);
|
|
127248
|
+
});
|
|
127249
|
+
}
|
|
127250
|
+
|
|
127251
|
+
// src/server/infra/lsp/lsp-proxy.ts
|
|
127252
|
+
init_worktrees();
|
|
127253
|
+
init_registry();
|
|
127254
|
+
var worktreeQueries2 = new WorktreeQueries();
|
|
127255
|
+
async function handleLspConnection(ws, req) {
|
|
127256
|
+
const url3 = new URL(req.url, `http://${req.headers.host}`);
|
|
127257
|
+
const worktreeId4 = url3.searchParams.get("worktreeId");
|
|
127258
|
+
const lang = url3.searchParams.get("lang");
|
|
127259
|
+
if (!worktreeId4 || !lang) {
|
|
127260
|
+
ws.close(4e3, "Missing worktreeId or lang");
|
|
127261
|
+
return;
|
|
127262
|
+
}
|
|
127263
|
+
await serveLspSocket(ws, worktreeId4, lang, async () => {
|
|
127264
|
+
const worktree = worktreeQueries2.findIdentity(worktreeId4);
|
|
127265
|
+
if (!worktree) {
|
|
127266
|
+
throw new Error(`Worktree not found: ${worktreeId4}`);
|
|
127267
|
+
}
|
|
127268
|
+
return hostRegistry.hostFor(worktreeId4).lsp.connect({ worktreeId: worktreeId4, lang, root: worktree.worktreePath });
|
|
127196
127269
|
});
|
|
127197
127270
|
}
|
|
127198
127271
|
|
|
@@ -127200,35 +127273,10 @@ async function handleLspConnection(ws, req) {
|
|
|
127200
127273
|
init_webhook2();
|
|
127201
127274
|
|
|
127202
127275
|
// src/server/services/_utils/byte-range.ts
|
|
127203
|
-
|
|
127204
|
-
const match = /^bytes=(\d*)-(\d*)$/.exec(header?.trim() ?? "");
|
|
127205
|
-
if (!match || match[1] === "" && match[2] === "") return null;
|
|
127206
|
-
if (match[1] !== "" && match[2] !== "" && Number(match[2]) < Number(match[1])) return null;
|
|
127207
|
-
let start;
|
|
127208
|
-
let end;
|
|
127209
|
-
if (match[1] === "") {
|
|
127210
|
-
const length = Number(match[2]);
|
|
127211
|
-
if (length === 0) return "unsatisfiable";
|
|
127212
|
-
start = Math.max(0, size - length);
|
|
127213
|
-
end = size - 1;
|
|
127214
|
-
} else {
|
|
127215
|
-
start = Number(match[1]);
|
|
127216
|
-
end = match[2] === "" ? size - 1 : Math.min(Number(match[2]), size - 1);
|
|
127217
|
-
}
|
|
127218
|
-
if (start >= size || start > end) return "unsatisfiable";
|
|
127219
|
-
return { start, end };
|
|
127220
|
-
}
|
|
127276
|
+
init_http_files();
|
|
127221
127277
|
|
|
127222
127278
|
// src/server/services/_utils/content-disposition.ts
|
|
127223
|
-
|
|
127224
|
-
const clean = filename.replace(/[/\\]/g, "_") || "download";
|
|
127225
|
-
const ascii = clean.replace(/[^\x20-\x7e]/g, "_").replace(/["%;]/g, "_");
|
|
127226
|
-
const encoded = encodeURIComponent(clean).replace(
|
|
127227
|
-
/['()*]/g,
|
|
127228
|
-
(c) => `%${c.charCodeAt(0).toString(16).toUpperCase()}`
|
|
127229
|
-
);
|
|
127230
|
-
return `attachment; filename="${ascii}"; filename*=UTF-8''${encoded}`;
|
|
127231
|
-
}
|
|
127279
|
+
init_http_files();
|
|
127232
127280
|
|
|
127233
127281
|
// src/server/services/_utils/hosted-file.ts
|
|
127234
127282
|
init_registry();
|
|
@@ -135387,15 +135435,15 @@ init_src();
|
|
|
135387
135435
|
init_registry();
|
|
135388
135436
|
async function installSkills2(opts = {}) {
|
|
135389
135437
|
const result = await hostRegistry.local.agentEnv.installSkills({ home: opts.home });
|
|
135390
|
-
const
|
|
135391
|
-
if (
|
|
135392
|
-
for (const warning of result.warnings)
|
|
135393
|
-
for (const path2 of result.written)
|
|
135438
|
+
const log95 = opts.log;
|
|
135439
|
+
if (log95) {
|
|
135440
|
+
for (const warning of result.warnings) log95.warn(warning);
|
|
135441
|
+
for (const path2 of result.written) log95.info("Installed skill at %s", path2);
|
|
135394
135442
|
for (const path2 of result.updated) {
|
|
135395
|
-
|
|
135443
|
+
log95.info("Updated skill at %s (content differed \u2014 shipped version reinstalled)", path2);
|
|
135396
135444
|
}
|
|
135397
135445
|
for (const conflict of result.conflicts) {
|
|
135398
|
-
|
|
135446
|
+
log95.warn("Skill symlink conflict \u2014 %s (left as-is; remove it manually to re-link)", conflict);
|
|
135399
135447
|
}
|
|
135400
135448
|
}
|
|
135401
135449
|
return result;
|
|
@@ -135408,7 +135456,7 @@ init_state();
|
|
|
135408
135456
|
init_sync_service();
|
|
135409
135457
|
init_worktree_group_service();
|
|
135410
135458
|
init_worktree_service();
|
|
135411
|
-
var
|
|
135459
|
+
var log94 = createLogger("setup");
|
|
135412
135460
|
async function runFirstTimeSetup() {
|
|
135413
135461
|
forgetLocalWorktrees();
|
|
135414
135462
|
convertLegacyLabels();
|
|
@@ -135421,7 +135469,7 @@ async function runFirstTimeSetup() {
|
|
|
135421
135469
|
]);
|
|
135422
135470
|
for (const r of results) {
|
|
135423
135471
|
if (r.status === "rejected") {
|
|
135424
|
-
|
|
135472
|
+
log94.warn(
|
|
135425
135473
|
"Setup step failed: %s",
|
|
135426
135474
|
r.reason instanceof Error ? r.reason.message : String(r.reason)
|
|
135427
135475
|
);
|
|
@@ -135435,7 +135483,7 @@ async function refreshAgentModelsInBackground() {
|
|
|
135435
135483
|
const ok2 = results.filter((r) => !r.error).length;
|
|
135436
135484
|
const failed = results.length - ok2;
|
|
135437
135485
|
if (results.length > 0) {
|
|
135438
|
-
|
|
135486
|
+
log94.info(
|
|
135439
135487
|
"Background model refresh: %d/%d agents updated (%d failed)",
|
|
135440
135488
|
ok2,
|
|
135441
135489
|
results.length,
|
|
@@ -135443,7 +135491,7 @@ async function refreshAgentModelsInBackground() {
|
|
|
135443
135491
|
);
|
|
135444
135492
|
}
|
|
135445
135493
|
} catch (err) {
|
|
135446
|
-
|
|
135494
|
+
log94.warn(
|
|
135447
135495
|
"Background model refresh failed: %s",
|
|
135448
135496
|
err instanceof Error ? err.message : String(err)
|
|
135449
135497
|
);
|
|
@@ -135458,7 +135506,7 @@ async function ensureRepoRemotes() {
|
|
|
135458
135506
|
try {
|
|
135459
135507
|
await repoService.backfillRemotes();
|
|
135460
135508
|
} catch (err) {
|
|
135461
|
-
|
|
135509
|
+
log94.warn(
|
|
135462
135510
|
"Failed to record repo remotes at boot: %s",
|
|
135463
135511
|
err instanceof Error ? err.message : String(err)
|
|
135464
135512
|
);
|
|
@@ -135468,7 +135516,7 @@ function migrateRepoCronjobs() {
|
|
|
135468
135516
|
try {
|
|
135469
135517
|
cronjobService.migrateRepoJobs();
|
|
135470
135518
|
} catch (err) {
|
|
135471
|
-
|
|
135519
|
+
log94.warn(
|
|
135472
135520
|
"Failed to move repo-scoped cronjobs to worktrees at boot: %s",
|
|
135473
135521
|
err instanceof Error ? err.message : String(err)
|
|
135474
135522
|
);
|
|
@@ -135478,7 +135526,7 @@ function convertLegacyLabels() {
|
|
|
135478
135526
|
try {
|
|
135479
135527
|
worktreeGroupService.convertLegacyLabels();
|
|
135480
135528
|
} catch (err) {
|
|
135481
|
-
|
|
135529
|
+
log94.warn(
|
|
135482
135530
|
"Failed to convert repo labels to groups at boot: %s",
|
|
135483
135531
|
err instanceof Error ? err.message : String(err)
|
|
135484
135532
|
);
|
|
@@ -135488,7 +135536,7 @@ function forgetLocalWorktrees() {
|
|
|
135488
135536
|
try {
|
|
135489
135537
|
worktreeService.forgetLocalWorktrees();
|
|
135490
135538
|
} catch (err) {
|
|
135491
|
-
|
|
135539
|
+
log94.warn(
|
|
135492
135540
|
"Failed to forget local worktrees at boot: %s",
|
|
135493
135541
|
err instanceof Error ? err.message : String(err)
|
|
135494
135542
|
);
|
|
@@ -135498,7 +135546,7 @@ async function ensureRepoStateInSync() {
|
|
|
135498
135546
|
try {
|
|
135499
135547
|
await syncService.syncWorktrees();
|
|
135500
135548
|
} catch (err) {
|
|
135501
|
-
|
|
135549
|
+
log94.warn(
|
|
135502
135550
|
"Failed to sync repo state at boot: %s",
|
|
135503
135551
|
err instanceof Error ? err.message : String(err)
|
|
135504
135552
|
);
|
|
@@ -135509,22 +135557,22 @@ async function ensureCliInstalled() {
|
|
|
135509
135557
|
try {
|
|
135510
135558
|
cliStatus = await checkCli();
|
|
135511
135559
|
} catch (err) {
|
|
135512
|
-
|
|
135560
|
+
log94.warn("Could not check CLI status: %s", err instanceof Error ? err.message : String(err));
|
|
135513
135561
|
return;
|
|
135514
135562
|
}
|
|
135515
135563
|
if (cliStatus === "Installed") {
|
|
135516
135564
|
return;
|
|
135517
135565
|
}
|
|
135518
135566
|
if (cliStatus !== "NotInstalled") {
|
|
135519
|
-
|
|
135567
|
+
log94.warn("CLI not auto-installed (status: %s)", cliStatus);
|
|
135520
135568
|
return;
|
|
135521
135569
|
}
|
|
135522
|
-
|
|
135570
|
+
log94.info("Installing band CLI...");
|
|
135523
135571
|
try {
|
|
135524
135572
|
await installCli();
|
|
135525
|
-
|
|
135573
|
+
log94.info("CLI installed to %s", SYMLINK_PATH);
|
|
135526
135574
|
} catch (err) {
|
|
135527
|
-
|
|
135575
|
+
log94.warn("CLI installation failed: %s", err instanceof Error ? err.message : String(err));
|
|
135528
135576
|
}
|
|
135529
135577
|
}
|
|
135530
135578
|
async function ensureDefaultCodingAgents() {
|
|
@@ -135533,17 +135581,17 @@ async function ensureDefaultCodingAgents() {
|
|
|
135533
135581
|
if (Array.isArray(existing) && existing.length > 0) {
|
|
135534
135582
|
return;
|
|
135535
135583
|
}
|
|
135536
|
-
|
|
135584
|
+
log94.info("Detecting installed coding agents...");
|
|
135537
135585
|
const detected = [];
|
|
135538
135586
|
for (const check3 of AGENT_CHECKS) {
|
|
135539
135587
|
const path2 = await systemService.whichBinary(check3.binary);
|
|
135540
135588
|
if (path2) {
|
|
135541
|
-
|
|
135589
|
+
log94.info("Detected coding agent: %s (%s)", check3.id, path2);
|
|
135542
135590
|
detected.push({ id: check3.id, type: check3.type, label: check3.label });
|
|
135543
135591
|
}
|
|
135544
135592
|
}
|
|
135545
135593
|
if (detected.length === 0) {
|
|
135546
|
-
|
|
135594
|
+
log94.info("No coding agent CLIs detected on PATH");
|
|
135547
135595
|
return;
|
|
135548
135596
|
}
|
|
135549
135597
|
const current3 = loadSettings();
|
|
@@ -135552,7 +135600,7 @@ async function ensureDefaultCodingAgents() {
|
|
|
135552
135600
|
current3.defaultCodingAgent = detected[0].id;
|
|
135553
135601
|
}
|
|
135554
135602
|
saveSettings(current3);
|
|
135555
|
-
|
|
135603
|
+
log94.info("Enabled %d coding agent(s); default = %s", detected.length, current3.defaultCodingAgent);
|
|
135556
135604
|
}
|
|
135557
135605
|
function ensureNotificationDefaults() {
|
|
135558
135606
|
const settings3 = loadSettings();
|
|
@@ -135564,7 +135612,7 @@ function ensureNotificationDefaults() {
|
|
|
135564
135612
|
...settings3,
|
|
135565
135613
|
notifications: { ...notifications, soundOnNeedsAttention: true }
|
|
135566
135614
|
});
|
|
135567
|
-
|
|
135615
|
+
log94.info("Set default notifications.soundOnNeedsAttention = true");
|
|
135568
135616
|
}
|
|
135569
135617
|
function migrateAgentDefaultMode() {
|
|
135570
135618
|
const settings3 = loadSettings();
|
|
@@ -135572,15 +135620,15 @@ function migrateAgentDefaultMode() {
|
|
|
135572
135620
|
const mode = agentModeFromVia(settings3.cli?.defaultVia);
|
|
135573
135621
|
if (!mode) return;
|
|
135574
135622
|
saveSettings({ ...settings3, agents: { ...settings3.agents, defaultMode: mode } });
|
|
135575
|
-
|
|
135623
|
+
log94.info("Migrated cli.defaultVia to agents.defaultMode = %s", mode);
|
|
135576
135624
|
}
|
|
135577
135625
|
async function ensureSkillsInstalled() {
|
|
135578
135626
|
try {
|
|
135579
|
-
const result = await installSkills2({ log:
|
|
135627
|
+
const result = await installSkills2({ log: log94 });
|
|
135580
135628
|
const wrote = result.written.length + result.updated.length;
|
|
135581
135629
|
const linkChange = result.linked.length;
|
|
135582
135630
|
if (wrote > 0 || linkChange > 0 || result.conflicts.length > 0) {
|
|
135583
|
-
|
|
135631
|
+
log94.info(
|
|
135584
135632
|
"Synced CLI skills (shared: %d written, %d updated, %d unchanged; symlinks: %d created, %d already-linked, %d conflicts, %d skipped)",
|
|
135585
135633
|
result.written.length,
|
|
135586
135634
|
result.updated.length,
|
|
@@ -135592,7 +135640,7 @@ async function ensureSkillsInstalled() {
|
|
|
135592
135640
|
);
|
|
135593
135641
|
}
|
|
135594
135642
|
} catch (err) {
|
|
135595
|
-
|
|
135643
|
+
log94.warn("Failed to sync CLI skills: %s", err instanceof Error ? err.message : String(err));
|
|
135596
135644
|
}
|
|
135597
135645
|
}
|
|
135598
135646
|
var SetupService = class {
|
|
@@ -135732,13 +135780,6 @@ function getCachedScalarHtml() {
|
|
|
135732
135780
|
_scalarHtml = getScalarHtml("/api/openapi.json");
|
|
135733
135781
|
return _scalarHtml;
|
|
135734
135782
|
}
|
|
135735
|
-
function hostedFileHeaders(contentType) {
|
|
135736
|
-
const headers = { "X-Content-Type-Options": "nosniff" };
|
|
135737
|
-
if (/^(text\/html|image\/svg\+xml)\b/.test(contentType)) {
|
|
135738
|
-
headers["Content-Security-Policy"] = "sandbox allow-scripts";
|
|
135739
|
-
}
|
|
135740
|
-
return headers;
|
|
135741
|
-
}
|
|
135742
135783
|
function serveStaticFile(res, root, subdir, rawFilename) {
|
|
135743
135784
|
const filename = basename7(decodeURIComponent(rawFilename));
|
|
135744
135785
|
if (!filename || filename.includes("..")) {
|