@band-app/server 0.59.0 → 0.60.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.
Files changed (72) hide show
  1. package/dist/client/_shell.html +0 -0
  2. package/dist/client/assets/{TerminalPanel-Dls8_vGY.js → TerminalPanel-B15ghqjC.js} +1 -1
  3. package/dist/client/assets/{_basePickBy-B5gHumRZ.js → _basePickBy-DnTEmDSj.js} +1 -1
  4. package/dist/client/assets/{_baseUniq-Bk4j3bVH.js → _baseUniq-vhCiyIYf.js} +1 -1
  5. package/dist/client/assets/{arc-BE7I7FD7.js → arc-CZ4Bw9uS.js} +1 -1
  6. package/dist/client/assets/{architectureDiagram-VXUJARFQ-BBWBwpgm.js → architectureDiagram-VXUJARFQ-CvqgWcYx.js} +1 -1
  7. package/dist/client/assets/{blockDiagram-VD42YOAC-CfFgUppR.js → blockDiagram-VD42YOAC-D8REfakL.js} +1 -1
  8. package/dist/client/assets/{c4Diagram-YG6GDRKO-ClgEIcXl.js → c4Diagram-YG6GDRKO-BIgJnhrx.js} +1 -1
  9. package/dist/client/assets/channel-DaBOqDcm.js +1 -0
  10. package/dist/client/assets/{chunk-4BX2VUAB-BTsFCzlB.js → chunk-4BX2VUAB-BO8PrQP3.js} +1 -1
  11. package/dist/client/assets/{chunk-55IACEB6-HURI4nLM.js → chunk-55IACEB6-DO5fHd1T.js} +1 -1
  12. package/dist/client/assets/{chunk-B4BG7PRW-rC-ot-Mn.js → chunk-B4BG7PRW-CAtAtkCf.js} +1 -1
  13. package/dist/client/assets/{chunk-DI55MBZ5-C2_9NN7e.js → chunk-DI55MBZ5-DRnZO_Tx.js} +1 -1
  14. package/dist/client/assets/{chunk-FMBD7UC4-CyCfpT3p.js → chunk-FMBD7UC4-DzqqzV_F.js} +1 -1
  15. package/dist/client/assets/{chunk-QN33PNHL-BbkJTAOV.js → chunk-QN33PNHL-DETRpC4Q.js} +1 -1
  16. package/dist/client/assets/{chunk-QZHKN3VN-BSdemm5A.js → chunk-QZHKN3VN-D6X6jOAA.js} +1 -1
  17. package/dist/client/assets/{chunk-TZMSLE5B-D4wvd9Yu.js → chunk-TZMSLE5B-C8IfJ5NA.js} +1 -1
  18. package/dist/client/assets/classDiagram-2ON5EDUG-CovRsOYg.js +1 -0
  19. package/dist/client/assets/classDiagram-v2-WZHVMYZB-CovRsOYg.js +1 -0
  20. package/dist/client/assets/clone-CEAieby9.js +1 -0
  21. package/dist/client/assets/{cose-bilkent-S5V4N54A-J0yf-ZRd.js → cose-bilkent-S5V4N54A-DMKRB7Bs.js} +1 -1
  22. package/dist/client/assets/{dagre-6UL2VRFP-D2ktTA5V.js → dagre-6UL2VRFP-C_cXM9p2.js} +1 -1
  23. package/dist/client/assets/{diagram-PSM6KHXK-DlQLNiTP.js → diagram-PSM6KHXK-D_A2BJh_.js} +1 -1
  24. package/dist/client/assets/{diagram-QEK2KX5R-oY37vdEd.js → diagram-QEK2KX5R-BnKjlyrI.js} +1 -1
  25. package/dist/client/assets/{diagram-S2PKOQOG-DaOX0asw.js → diagram-S2PKOQOG-R4tiwc1I.js} +1 -1
  26. package/dist/client/assets/{erDiagram-Q2GNP2WA-BeewDnEp.js → erDiagram-Q2GNP2WA-CNV08IQO.js} +1 -1
  27. package/dist/client/assets/{flowDiagram-NV44I4VS-CgEQ2bXi.js → flowDiagram-NV44I4VS-BAXwfe4s.js} +1 -1
  28. package/dist/client/assets/{ganttDiagram-JELNMOA3-DLIhunms.js → ganttDiagram-JELNMOA3-Bk3PXBP9.js} +1 -1
  29. package/dist/client/assets/{gitGraphDiagram-V2S2FVAM-BbcljkLL.js → gitGraphDiagram-V2S2FVAM-C8tujQgm.js} +1 -1
  30. package/dist/client/assets/{graph-C1SThxwq.js → graph-BIBqorc8.js} +1 -1
  31. package/dist/client/assets/{highlighted-body-B3W2YXNL-6fAWPSpW.js → highlighted-body-B3W2YXNL-NymhDWI2.js} +1 -1
  32. package/dist/client/assets/{index-Bxgl3ZHO.js → index-BKBEQAUS.js} +1 -1
  33. package/dist/client/assets/{index-D7f6vSSM.js → index-BYs8YaN9.js} +1 -1
  34. package/dist/client/assets/{index-B1SUzFra.js → index-BYzUhLmm.js} +1 -1
  35. package/dist/client/assets/{index-DNW-icyC.js → index-BvS6Fo_E.js} +1 -1
  36. package/dist/client/assets/{index-DWbGgUyQ.js → index-C6Buf5vO.js} +1 -1
  37. package/dist/client/assets/{index-Bh3TSdKT.js → index-Cqclrque.js} +1 -1
  38. package/dist/client/assets/{index-D13XFok4.js → index-D9qmTeqK.js} +1 -1
  39. package/dist/client/assets/{index-CLieczz3.js → index-DJlBcjuS.js} +1 -1
  40. package/dist/client/assets/{index-BAfOs6Gy.js → index-DSUNlkvo.js} +1 -1
  41. package/dist/client/assets/{index-5YEiuPMI.js → index-Dc6DOl2V.js} +1 -1
  42. package/dist/client/assets/{index-Bk8JlBY0.js → index-Dg2MZcDG.js} +1 -1
  43. package/dist/client/assets/{index-CiOhy6I5.js → index-PQDlzdDe.js} +1 -1
  44. package/dist/client/assets/{index-DMWW3BkM.js → index-secZqOa5.js} +1 -1
  45. package/dist/client/assets/{infoDiagram-HS3SLOUP-vyRt2Bsk.js → infoDiagram-HS3SLOUP-GzU-nr0a.js} +1 -1
  46. package/dist/client/assets/{journeyDiagram-XKPGCS4Q-DBXVmGpv.js → journeyDiagram-XKPGCS4Q-Dv_GZIcq.js} +1 -1
  47. package/dist/client/assets/{kanban-definition-3W4ZIXB7-CEpw89r7.js → kanban-definition-3W4ZIXB7-BuCDku9Z.js} +1 -1
  48. package/dist/client/assets/{layout-Q53PNtzV.js → layout-C1BWvm3U.js} +1 -1
  49. package/dist/client/assets/{main-doYM8mtx.js → main-CW1tJAHn.js} +297 -297
  50. package/dist/client/assets/main-CYIZgqYb.css +1 -0
  51. package/dist/client/assets/{mindmap-definition-VGOIOE7T-jFXUryZ1.js → mindmap-definition-VGOIOE7T-D-ySOJ80.js} +1 -1
  52. package/dist/client/assets/{pieDiagram-ADFJNKIX-24FHt1PP.js → pieDiagram-ADFJNKIX-BCPXro4s.js} +1 -1
  53. package/dist/client/assets/{quadrantDiagram-AYHSOK5B-BznmAQTy.js → quadrantDiagram-AYHSOK5B-6iX-Hvg-.js} +1 -1
  54. package/dist/client/assets/{requirementDiagram-UZGBJVZJ-auw6LsZk.js → requirementDiagram-UZGBJVZJ-CZu5itKP.js} +1 -1
  55. package/dist/client/assets/{sankeyDiagram-TZEHDZUN-CX_06gNQ.js → sankeyDiagram-TZEHDZUN-C7dzQDVd.js} +1 -1
  56. package/dist/client/assets/{sequenceDiagram-WL72ISMW-tQMk7iIO.js → sequenceDiagram-WL72ISMW-Q9GYKo64.js} +1 -1
  57. package/dist/client/assets/{stateDiagram-FKZM4ZOC-DCZeLtBb.js → stateDiagram-FKZM4ZOC-DcAjq5pM.js} +1 -1
  58. package/dist/client/assets/stateDiagram-v2-4FDKWEC3-D0LqsI9r.js +1 -0
  59. package/dist/client/assets/{timeline-definition-IT6M3QCI-CqegSAwa.js → timeline-definition-IT6M3QCI-CkyryJCh.js} +1 -1
  60. package/dist/client/assets/{treemap-GDKQZRPO-C1eLC_yq.js → treemap-GDKQZRPO-BW9t3c2Z.js} +1 -1
  61. package/dist/client/assets/{worktree._worktreeId-BfJo-vJP.js → worktree._worktreeId-BvQb_KmW.js} +1 -1
  62. package/dist/client/assets/{worktree._worktreeId-CNBIqdCa.js → worktree._worktreeId-CWpDyVL-.js} +1 -1
  63. package/dist/client/assets/{xychartDiagram-PRI3JC2R-CDiV-aAA.js → xychartDiagram-PRI3JC2R-DxUmnBlk.js} +1 -1
  64. package/dist/openapi.json +199 -197
  65. package/dist/start-server.mjs +138 -157
  66. package/package.json +10 -10
  67. package/dist/client/assets/channel-CLuseuD8.js +0 -1
  68. package/dist/client/assets/classDiagram-2ON5EDUG-PhOyZKeC.js +0 -1
  69. package/dist/client/assets/classDiagram-v2-WZHVMYZB-PhOyZKeC.js +0 -1
  70. package/dist/client/assets/clone-CMv9qsOc.js +0 -1
  71. package/dist/client/assets/main-BVyM6Kwo.css +0 -1
  72. package/dist/client/assets/stateDiagram-v2-4FDKWEC3-9Yihsv84.js +0 -1
@@ -15184,7 +15184,7 @@ var require_stream = __commonJS({
15184
15184
  };
15185
15185
  duplex._final = function(callback) {
15186
15186
  if (ws.readyState === ws.CONNECTING) {
15187
- ws.once("open", function open4() {
15187
+ ws.once("open", function open3() {
15188
15188
  duplex._final(callback);
15189
15189
  });
15190
15190
  return;
@@ -15205,7 +15205,7 @@ var require_stream = __commonJS({
15205
15205
  };
15206
15206
  duplex._write = function(chunk, encoding, callback) {
15207
15207
  if (ws.readyState === ws.CONNECTING) {
15208
- ws.once("open", function open4() {
15208
+ ws.once("open", function open3() {
15209
15209
  duplex._write(chunk, encoding, callback);
15210
15210
  });
15211
15211
  return;
@@ -67486,14 +67486,14 @@ function pickPullRequest(allNodes, repoOwner2, isDefaultBranch) {
67486
67486
  );
67487
67487
  const node2 = nodes2.find((n) => n.state === "OPEN") ?? (isDefaultBranch ? void 0 : nodes2.find((n) => n.state === "MERGED") ?? nodes2.find((n) => n.state === "CLOSED"));
67488
67488
  if (!node2) return null;
67489
- const open4 = node2.state === "OPEN";
67490
- const mergeQueue = open4 ? parseMergeQueue(node2) : null;
67491
- const autoMerge = open4 ? parseAutoMerge(node2) : null;
67489
+ const open3 = node2.state === "OPEN";
67490
+ const mergeQueue = open3 ? parseMergeQueue(node2) : null;
67491
+ const autoMerge = open3 ? parseAutoMerge(node2) : null;
67492
67492
  return {
67493
67493
  number: node2.number,
67494
67494
  title: node2.title,
67495
67495
  url: node2.url,
67496
- state: open4 ? "open" : node2.state === "MERGED" ? "merged" : "closed",
67496
+ state: open3 ? "open" : node2.state === "MERGED" ? "merged" : "closed",
67497
67497
  isDraft: node2.isDraft,
67498
67498
  ...mergeQueue && { mergeQueue },
67499
67499
  ...autoMerge && { autoMerge }
@@ -75671,8 +75671,8 @@ var init_placement_service = __esm({
75671
75671
  */
75672
75672
  async placeWorktree(input3, placement) {
75673
75673
  const worktreeId4 = toWorktreeId(input3.repo, input3.branch, void 0);
75674
- const open4 = this.queries.findOpenForWorktree(worktreeId4);
75675
- if (open4) return { kind: "request", requestId: open4.id };
75674
+ const open3 = this.queries.findOpenForWorktree(worktreeId4);
75675
+ if (open3) return { kind: "request", requestId: open3.id };
75676
75676
  const holders = this.holdersOfRemotelessRepo(input3.repo);
75677
75677
  const agent = input3.codingAgentId ? loadSettings().codingAgents?.find((a) => a.id === input3.codingAgentId)?.type ?? input3.codingAgentId : void 0;
75678
75678
  const allowed2 = allowedHostsOf(input3.repo);
@@ -75740,8 +75740,8 @@ var init_placement_service = __esm({
75740
75740
  requestWake(wake, repo, branch) {
75741
75741
  const first = wake.worktreeIds[0];
75742
75742
  if (!first) throw new Error("A wake request names no worktree");
75743
- const open4 = this.queries.findOpenForWorktree(first);
75744
- if (open4) return open4;
75743
+ const open3 = this.queries.findOpenForWorktree(first);
75744
+ if (open3) return open3;
75745
75745
  const earlier = this.queries.latestForHost(wake.hostId);
75746
75746
  const now = this.now();
75747
75747
  const row = {
@@ -79141,13 +79141,13 @@ var init_agent_session_registry_service = __esm({
79141
79141
  * agent sessions gets its row here, the first time its id is known.
79142
79142
  */
79143
79143
  recordChatProviderSession(chat, providerSessionId) {
79144
- const open4 = this.queries.findOpenByChat(chat.id);
79145
- if (open4 && open4.providerSessionId === providerSessionId) return;
79146
- if (open4 && open4.providerSessionId === null) {
79147
- if (providerSessionId) this.update(open4.id, { providerSessionId, state: "running" });
79144
+ const open3 = this.queries.findOpenByChat(chat.id);
79145
+ if (open3 && open3.providerSessionId === providerSessionId) return;
79146
+ if (open3 && open3.providerSessionId === null) {
79147
+ if (providerSessionId) this.update(open3.id, { providerSessionId, state: "running" });
79148
79148
  return;
79149
79149
  }
79150
- if (open4) this.end(open4.id);
79150
+ if (open3) this.end(open3.id);
79151
79151
  if (!providerSessionId) return;
79152
79152
  this.create({
79153
79153
  worktreeId: chat.worktreeId,
@@ -79158,12 +79158,12 @@ var init_agent_session_registry_service = __esm({
79158
79158
  });
79159
79159
  }
79160
79160
  endForChat(chatId) {
79161
- const open4 = this.queries.findOpenByChat(chatId);
79162
- if (open4) this.end(open4.id);
79161
+ const open3 = this.queries.findOpenByChat(chatId);
79162
+ if (open3) this.end(open3.id);
79163
79163
  }
79164
79164
  endForTerminal(terminalId) {
79165
- const open4 = this.queries.findOpenByTerminal(terminalId);
79166
- if (open4) this.end(open4.id);
79165
+ const open3 = this.queries.findOpenByTerminal(terminalId);
79166
+ if (open3) this.end(open3.id);
79167
79167
  }
79168
79168
  end(id) {
79169
79169
  const ended = this.queries.update(id, { state: "ended", updatedAt: Date.now() });
@@ -111928,8 +111928,6 @@ var agentSessionsRouter = t.router({
111928
111928
  // src/server/api/browser-host/router.ts
111929
111929
  init_src();
111930
111930
  init_zod();
111931
- import { constants as fsConstants, open as open3 } from "node:fs/promises";
111932
- import { extname as extname2, isAbsolute as isAbsolute3 } from "node:path";
111933
111931
 
111934
111932
  // src/server/infra/browser-host/host-state.ts
111935
111933
  init_src();
@@ -112065,123 +112063,6 @@ var browserHostService = new BrowserHostService();
112065
112063
 
112066
112064
  // src/server/api/browser-host/router.ts
112067
112065
  var log63 = createLogger("trpc.browser-host");
112068
- var MAX_FILE_SIZE = 1024 * 1024;
112069
- var LANG_MAP = {
112070
- ".js": "javascript",
112071
- ".jsx": "jsx",
112072
- ".ts": "typescript",
112073
- ".tsx": "tsx",
112074
- ".mjs": "javascript",
112075
- ".cjs": "javascript",
112076
- ".json": "json",
112077
- ".html": "html",
112078
- ".css": "css",
112079
- ".scss": "scss",
112080
- ".md": "markdown",
112081
- ".yaml": "yaml",
112082
- ".yml": "yaml",
112083
- ".toml": "toml",
112084
- ".py": "python",
112085
- ".rb": "ruby",
112086
- ".rs": "rust",
112087
- ".go": "go",
112088
- ".java": "java",
112089
- ".swift": "swift",
112090
- ".c": "c",
112091
- ".cpp": "cpp",
112092
- ".sh": "bash",
112093
- ".sql": "sql",
112094
- ".graphql": "graphql",
112095
- ".vue": "vue",
112096
- ".svelte": "svelte",
112097
- ".diff": "diff"
112098
- };
112099
- function mapFsError(err) {
112100
- const code = err.code;
112101
- if (code === "ENOENT") return new Error("File not found");
112102
- if (code === "ELOOP") return new Error("Symbolic links are not allowed");
112103
- if (code === "EACCES" || code === "EPERM") return new Error("Permission denied");
112104
- if (code === "EISDIR") return new Error("Cannot operate on a directory");
112105
- return err instanceof Error ? err : new Error(String(err));
112106
- }
112107
- var hostRouter = t.router({
112108
- readFile: publicProcedure.input(external_exports2.object({ absolutePath: external_exports2.string().min(1) })).query(async ({ input: input3 }) => {
112109
- const target = input3.absolutePath;
112110
- if (!isAbsolute3(target)) {
112111
- throw new Error("Absolute path required");
112112
- }
112113
- let fh;
112114
- try {
112115
- fh = await open3(target, fsConstants.O_RDONLY | fsConstants.O_NOFOLLOW);
112116
- } catch (err) {
112117
- throw mapFsError(err);
112118
- }
112119
- try {
112120
- const stats = await fh.stat();
112121
- if (stats.isDirectory()) {
112122
- throw new Error("Cannot operate on a directory");
112123
- }
112124
- if (!stats.isFile()) {
112125
- throw new Error("Not a regular file");
112126
- }
112127
- const size = stats.size;
112128
- if (size > MAX_FILE_SIZE) {
112129
- return { tooLarge: true, size };
112130
- }
112131
- const sampleLen = Math.min(8192, size);
112132
- const sample = Buffer.alloc(sampleLen);
112133
- if (sampleLen > 0) {
112134
- await fh.read(sample, 0, sampleLen, 0);
112135
- if (sample.includes(0)) {
112136
- return { binary: true, size };
112137
- }
112138
- }
112139
- const buffer = await fh.readFile();
112140
- const ext = extname2(target).toLowerCase();
112141
- const language = LANG_MAP[ext];
112142
- return {
112143
- content: buffer.toString("utf-8"),
112144
- size,
112145
- language
112146
- };
112147
- } finally {
112148
- await fh.close();
112149
- }
112150
- }),
112151
- saveFile: publicProcedure.input(
112152
- external_exports2.object({
112153
- absolutePath: external_exports2.string().min(1),
112154
- // Match the read-side cap so a misbehaving client can't fill
112155
- // disk via the save endpoint while the read endpoint refuses
112156
- // anything that wide.
112157
- content: external_exports2.string().max(MAX_FILE_SIZE)
112158
- })
112159
- ).mutation(async ({ input: input3 }) => {
112160
- const target = input3.absolutePath;
112161
- if (!isAbsolute3(target)) {
112162
- throw new Error("Absolute path required");
112163
- }
112164
- let fh;
112165
- try {
112166
- fh = await open3(
112167
- target,
112168
- fsConstants.O_WRONLY | fsConstants.O_TRUNC | fsConstants.O_NOFOLLOW
112169
- );
112170
- } catch (err) {
112171
- throw mapFsError(err);
112172
- }
112173
- try {
112174
- const stats = await fh.stat();
112175
- if (!stats.isFile()) {
112176
- throw new Error("Not a regular file");
112177
- }
112178
- await fh.writeFile(input3.content, "utf-8");
112179
- } finally {
112180
- await fh.close();
112181
- }
112182
- return { ok: true };
112183
- })
112184
- });
112185
112066
  var browserHostRouter = t.router({
112186
112067
  // Diagnostic: the desktop's BrowserHostBridge calls this on mount so we
112187
112068
  // can confirm in the server log that the bridge component actually
@@ -113262,7 +113143,7 @@ function formatFileLocation(filePath, line2, options) {
113262
113143
 
113263
113144
  // ../../packages/worktree-ops/src/resolve-path.ts
113264
113145
  init_resolver();
113265
- import { isAbsolute as isAbsolute4, join as join52, resolve as resolve10, sep as sep6 } from "node:path";
113146
+ import { isAbsolute as isAbsolute3, join as join52, resolve as resolve10, sep as sep6 } from "node:path";
113266
113147
  var PathsService = class {
113267
113148
  constructor(worktrees2) {
113268
113149
  this.worktrees = worktrees2;
@@ -113280,7 +113161,7 @@ var PathsService = class {
113280
113161
  }
113281
113162
  };
113282
113163
  async function resolveTarget(fs3, root, filePath) {
113283
- const absoluteTarget = isAbsolute4(filePath) ? resolve10(filePath) : resolve10(root, filePath);
113164
+ const absoluteTarget = isAbsolute3(filePath) ? resolve10(filePath) : resolve10(root, filePath);
113284
113165
  let canonicalRoot = root;
113285
113166
  try {
113286
113167
  canonicalRoot = await fs3.realpath(root);
@@ -113395,10 +113276,10 @@ async function pumpChanges(worktreeId4, entry, host, root) {
113395
113276
  for (const listener of entry.listeners) listener(null);
113396
113277
  stopWatcher(worktreeId4, entry);
113397
113278
  }
113398
- function subscribeToFileChanges(worktreeId4, open4, listener) {
113279
+ function subscribeToFileChanges(worktreeId4, open3, listener) {
113399
113280
  let entry = watchers.get(worktreeId4);
113400
113281
  if (!entry) {
113401
- const target = open4();
113282
+ const target = open3();
113402
113283
  if (!target) return () => {
113403
113284
  };
113404
113285
  entry = { controller: new AbortController(), listeners: /* @__PURE__ */ new Set(), pendingTimers: /* @__PURE__ */ new Map() };
@@ -113429,7 +113310,7 @@ function subscribeToFileChanges2(worktreeId4, listener) {
113429
113310
  // src/server/services/formatter.ts
113430
113311
  init_src();
113431
113312
  init_registry();
113432
- import { basename as basename4, dirname as dirname15, isAbsolute as isAbsolute5, join as join53, resolve as resolvePath3 } from "node:path";
113313
+ import { basename as basename4, dirname as dirname15, isAbsolute as isAbsolute4, join as join53, resolve as resolvePath3 } from "node:path";
113433
113314
  import prettier from "prettier";
113434
113315
  var log65 = createLogger("formatter");
113435
113316
  var FormatterError = class extends Error {
@@ -113445,7 +113326,7 @@ var FormatterError = class extends Error {
113445
113326
  async function formatFile(worktreePath, filePath, content, options = {}) {
113446
113327
  const fs3 = options.fs ?? hostRegistry.local.fs;
113447
113328
  const onHub = fs3 === hostRegistry.local.fs;
113448
- const absFile = isAbsolute5(filePath) ? filePath : resolvePath3(worktreePath, filePath);
113329
+ const absFile = isAbsolute4(filePath) ? filePath : resolvePath3(worktreePath, filePath);
113449
113330
  if (!await isInsideWorktree(fs3, absFile, worktreePath)) {
113450
113331
  throw new FormatterError(
113451
113332
  "FILE_NOT_IN_WORKTREE",
@@ -113735,7 +113616,7 @@ init_environment_build_service();
113735
113616
  init_src6();
113736
113617
  init_dist();
113737
113618
  init_registry();
113738
- import { basename as basename5, dirname as dirname16, isAbsolute as isAbsolute6 } from "node:path";
113619
+ import { basename as basename5, dirname as dirname16, isAbsolute as isAbsolute5 } from "node:path";
113739
113620
  init_token_service();
113740
113621
  var EnvironmentService = class {
113741
113622
  /** The environment of a repo's main checkout, and which hosts meet its `requires`. */
@@ -113750,7 +113631,7 @@ var EnvironmentService = class {
113750
113631
  * name the `.band/environment.json` file itself.
113751
113632
  */
113752
113633
  async validatePath(path2) {
113753
- if (!isAbsolute6(path2)) {
113634
+ if (!isAbsolute5(path2)) {
113754
113635
  throw new TRPCError({ code: "BAD_REQUEST", message: "path must be absolute" });
113755
113636
  }
113756
113637
  const isFile2 = basename5(path2) === "environment.json" && basename5(dirname16(path2)) === ".band";
@@ -114850,7 +114731,7 @@ init_registry();
114850
114731
  // package.json
114851
114732
  var package_default = {
114852
114733
  name: "@band-app/server",
114853
- version: "0.59.0",
114734
+ version: "0.60.0",
114854
114735
  type: "module",
114855
114736
  types: "src/index.ts",
114856
114737
  exports: {
@@ -124320,6 +124201,92 @@ var DirectAccessService = class {
124320
124201
  };
124321
124202
  var directAccessService = new DirectAccessService();
124322
124203
 
124204
+ // src/server/services/external-file-service.ts
124205
+ init_errors6();
124206
+ init_worktree_service();
124207
+ import { extname as extname2, isAbsolute as isAbsolute6 } from "node:path";
124208
+ var MAX_FILE_SIZE = 1024 * 1024;
124209
+ var LANG_MAP = {
124210
+ ".js": "javascript",
124211
+ ".jsx": "jsx",
124212
+ ".ts": "typescript",
124213
+ ".tsx": "tsx",
124214
+ ".mjs": "javascript",
124215
+ ".cjs": "javascript",
124216
+ ".json": "json",
124217
+ ".html": "html",
124218
+ ".css": "css",
124219
+ ".scss": "scss",
124220
+ ".md": "markdown",
124221
+ ".yaml": "yaml",
124222
+ ".yml": "yaml",
124223
+ ".toml": "toml",
124224
+ ".py": "python",
124225
+ ".rb": "ruby",
124226
+ ".rs": "rust",
124227
+ ".go": "go",
124228
+ ".java": "java",
124229
+ ".swift": "swift",
124230
+ ".c": "c",
124231
+ ".cpp": "cpp",
124232
+ ".sh": "bash",
124233
+ ".sql": "sql",
124234
+ ".graphql": "graphql",
124235
+ ".vue": "vue",
124236
+ ".svelte": "svelte",
124237
+ ".diff": "diff"
124238
+ };
124239
+ function hostFor2(worktreeId4) {
124240
+ const resolved = worktreeService.resolve(worktreeId4);
124241
+ if (!resolved) throw new WorktreeNotFoundError(worktreeId4);
124242
+ return resolved.host;
124243
+ }
124244
+ async function statFile(fs3, path2) {
124245
+ try {
124246
+ return await fs3.stat(path2);
124247
+ } catch (err) {
124248
+ const text4 = err instanceof Error ? `${err.code ?? ""} ${err.message}` : "";
124249
+ if (/ENOENT|no such file|not found/i.test(text4)) throw new Error("File not found");
124250
+ throw err;
124251
+ }
124252
+ }
124253
+ function assertAbsolute(path2) {
124254
+ if (!isAbsolute6(path2)) throw new Error("Absolute path required");
124255
+ }
124256
+ var ExternalFileService = class {
124257
+ async read(worktreeId4, absolutePath) {
124258
+ assertAbsolute(absolutePath);
124259
+ const { fs: fs3 } = hostFor2(worktreeId4);
124260
+ const stat9 = await statFile(fs3, absolutePath);
124261
+ if (stat9.kind === "symlink") throw new Error("Symbolic links are not allowed");
124262
+ if (stat9.kind === "directory") throw new Error("Cannot operate on a directory");
124263
+ if (stat9.kind !== "file") throw new Error("Not a regular file");
124264
+ if (stat9.size > MAX_FILE_SIZE) return { tooLarge: true, size: stat9.size };
124265
+ const bytes = await fs3.readFile(absolutePath);
124266
+ const buffer = Buffer.from(bytes.buffer, bytes.byteOffset, bytes.byteLength);
124267
+ if (buffer.subarray(0, 8192).includes(0)) return { binary: true, size: stat9.size };
124268
+ return {
124269
+ content: buffer.toString("utf-8"),
124270
+ size: stat9.size,
124271
+ language: LANG_MAP[extname2(absolutePath).toLowerCase()]
124272
+ };
124273
+ }
124274
+ async save(worktreeId4, absolutePath, content) {
124275
+ assertAbsolute(absolutePath);
124276
+ if (Buffer.byteLength(content, "utf-8") > MAX_FILE_SIZE) throw new Error("File too large");
124277
+ const { fs: fs3 } = hostFor2(worktreeId4);
124278
+ const stat9 = await statFile(fs3, absolutePath);
124279
+ if (stat9.kind === "symlink") throw new Error("Symbolic links are not allowed");
124280
+ if (stat9.kind !== "file") throw new Error("Not a regular file");
124281
+ if (absolutePath.split(/[\\/]/).includes(".git")) {
124282
+ throw new Error("Refusing to write inside a .git folder");
124283
+ }
124284
+ await fs3.writeFile(absolutePath, content);
124285
+ return { ok: true };
124286
+ }
124287
+ };
124288
+ var externalFileService = new ExternalFileService();
124289
+
124323
124290
  // ../../packages/worktree-ops/src/files.ts
124324
124291
  init_resolver();
124325
124292
  import { dirname as dirname18, extname as extname3, join as join59, resolve as resolve13, sep as sep10 } from "node:path";
@@ -125973,6 +125940,20 @@ var worktreeRouter = t.router({
125973
125940
  listFiles: publicProcedure.input(directOps["worktree.listFiles"].input).query(({ input: input3 }) => directOps["worktree.listFiles"].run(worktreeOps, input3)),
125974
125941
  getFile: publicProcedure.input(directOps["worktree.getFile"].input).query(({ input: input3 }) => directOps["worktree.getFile"].run(worktreeOps, input3)),
125975
125942
  saveFile: publicProcedure.input(directOps["worktree.saveFile"].input).mutation(({ input: input3 }) => directOps["worktree.saveFile"].run(worktreeOps, input3)),
125943
+ /**
125944
+ * A file outside the worktree, read on the worktree's own worker (never the
125945
+ * hub's disk). Left out of the relay and the direct path: device tokens only.
125946
+ */
125947
+ readExternalFile: publicProcedure.input(external_exports2.object({ worktreeId: external_exports2.string().min(1), absolutePath: external_exports2.string().min(1) })).query(({ input: input3 }) => externalFileService.read(input3.worktreeId, input3.absolutePath)),
125948
+ saveExternalFile: publicProcedure.input(
125949
+ external_exports2.object({
125950
+ worktreeId: external_exports2.string().min(1),
125951
+ absolutePath: external_exports2.string().min(1),
125952
+ content: external_exports2.string()
125953
+ })
125954
+ ).mutation(
125955
+ ({ input: input3 }) => externalFileService.save(input3.worktreeId, input3.absolutePath, input3.content)
125956
+ ),
125976
125957
  createFile: publicProcedure.input(directOps["worktree.createFile"].input).mutation(({ input: input3 }) => directOps["worktree.createFile"].run(worktreeOps, input3)),
125977
125958
  createDirectory: publicProcedure.input(directOps["worktree.createDirectory"].input).mutation(({ input: input3 }) => directOps["worktree.createDirectory"].run(worktreeOps, input3)),
125978
125959
  deletePath: publicProcedure.input(directOps["worktree.deletePath"].input).mutation(({ input: input3 }) => directOps["worktree.deletePath"].run(worktreeOps, input3)),
@@ -125997,7 +125978,7 @@ var worktreeRouter = t.router({
125997
125978
  // path an authenticated caller supplies (not just in-worktree ones), so it
125998
125979
  // is a filesystem-existence oracle. That is acceptable under Band's threat
125999
125980
  // model — the same auth scope already reads arbitrary absolute paths via
126000
- // `host.readFile` — and the `external` flag is load-bearing, not dead code:
125981
+ // `worktree.readExternalFile` — and the `external` flag is load-bearing, not dead code:
126001
125982
  // it's how the client decides between a worktree-relative and an external
126002
125983
  // tab. Do not "harden" this by dropping the out-of-worktree classification.
126003
125984
  resolvePath: publicProcedure.input(resolvePathInput).query(
@@ -126135,7 +126116,6 @@ var appRouter = t.router({
126135
126116
  accountUsage: accountUsageRouter,
126136
126117
  resources: resourcesRouter,
126137
126118
  hooks: hooksRouter,
126138
- host: hostRouter,
126139
126119
  workers: hostsRouter,
126140
126120
  // Old name, kept for desktop, mobile and CLI builds that still call it.
126141
126121
  hosts: hostsRouter,
@@ -126188,6 +126168,7 @@ function discoverProcedures() {
126188
126168
  continue;
126189
126169
  if (path2 === "worktree.previewUrl") continue;
126190
126170
  if (path2 === "worktree.directAccess") continue;
126171
+ if (path2 === "worktree.readExternalFile" || path2 === "worktree.saveExternalFile") continue;
126191
126172
  if (path2 === "environment.validate") continue;
126192
126173
  if (path2 === "repos.addFromWorker") continue;
126193
126174
  if (path2 === "repos.addByUrl") continue;
@@ -127370,7 +127351,7 @@ function parseModeRequest(text4) {
127370
127351
  }
127371
127352
  return null;
127372
127353
  }
127373
- async function bridgePluginStream(ws, label2, open4, onOpenFailed) {
127354
+ async function bridgePluginStream(ws, label2, open3, onOpenFailed) {
127374
127355
  let controlling = false;
127375
127356
  let stream = null;
127376
127357
  ws.on("message", (data, isBinary) => {
@@ -127388,7 +127369,7 @@ async function bridgePluginStream(ws, label2, open4, onOpenFailed) {
127388
127369
  });
127389
127370
  ws.once("close", () => stream?.close());
127390
127371
  try {
127391
- stream = await open4();
127372
+ stream = await open3();
127392
127373
  } catch (err) {
127393
127374
  const message = err instanceof Error ? err.message : String(err);
127394
127375
  log87.warn("%s is unavailable: %s", label2, message);
@@ -128289,18 +128270,18 @@ async function bridgeRemote(ws, worktreeId4) {
128289
128270
  ws.removeAllListeners("message");
128290
128271
  return pending2;
128291
128272
  }
128292
- const open4 = cdp;
128273
+ const open3 = cdp;
128293
128274
  if (ws.readyState !== ws.OPEN) {
128294
- open4.close();
128275
+ open3.close();
128295
128276
  return true;
128296
128277
  }
128297
- for (const msg of pending2) open4.send(msg);
128278
+ for (const msg of pending2) open3.send(msg);
128298
128279
  pending2.length = 0;
128299
- ws.on("close", () => open4.close());
128300
- ws.on("error", () => open4.close());
128280
+ ws.on("close", () => open3.close());
128281
+ ws.on("error", () => open3.close());
128301
128282
  void (async () => {
128302
128283
  try {
128303
- for await (const message of open4.messages) {
128284
+ for await (const message of open3.messages) {
128304
128285
  if (ws.readyState === ws.OPEN) ws.send(message);
128305
128286
  }
128306
128287
  } catch (err) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@band-app/server",
3
- "version": "0.59.0",
3
+ "version": "0.60.0",
4
4
  "type": "module",
5
5
  "types": "src/index.ts",
6
6
  "exports": {
@@ -58,24 +58,24 @@
58
58
  "vitest": "^4.0.18",
59
59
  "ws": "^8.18.0",
60
60
  "zod": "^3.25.67",
61
- "@band-app/coding-agent": "^0.59.0",
61
+ "@band-app/environment": "^0.1.0",
62
+ "@band-app/coding-agent": "^0.60.0",
62
63
  "@band-app/host-api": "^0.1.0",
63
64
  "@band-app/chat-runtime": "^0.1.0",
64
65
  "@band-app/host-local": "^0.1.0",
65
- "@band-app/environment": "^0.1.0",
66
66
  "@band-app/host-remote": "^0.1.0",
67
+ "@band-app/logger": "^0.60.0",
67
68
  "@band-app/plugin-api": "^0.1.0",
68
- "@band-app/plugin-github": "^0.1.0",
69
- "@band-app/link": "^0.1.0",
70
69
  "@band-app/shared": "^0.1.0",
71
- "@band-app/logger": "^0.59.0",
70
+ "@band-app/worktree-ops": "^0.1.0",
71
+ "@band-app/plugin-github": "^0.1.0",
72
72
  "@band-app/plugin-simulator": "^0.1.0",
73
- "@band-app/worktree-ops": "^0.1.0"
73
+ "@band-app/link": "^0.1.0"
74
74
  },
75
75
  "optionalDependencies": {
76
- "@band-app/worker-cli-darwin-arm64": "0.59.0",
77
- "@band-app/worker-cli-linux-x64": "0.59.0",
78
- "@band-app/worker-cli-linux-arm64": "0.59.0"
76
+ "@band-app/worker-cli-darwin-arm64": "0.60.0",
77
+ "@band-app/worker-cli-linux-x64": "0.60.0",
78
+ "@band-app/worker-cli-linux-arm64": "0.60.0"
79
79
  },
80
80
  "scripts": {
81
81
  "dev": "NODE_ENV=development tsx watch --exclude '../web/**' start-server.ts",
@@ -1 +0,0 @@
1
- import{Y as a,Z as n}from"./main-doYM8mtx.js";const t=(r,o)=>a.lang.round(n.parse(r)[o]);export{t as c};
@@ -1 +0,0 @@
1
- import{s as a,c as s,a as e,C as t}from"./chunk-B4BG7PRW-rC-ot-Mn.js";import{_ as i}from"./main-doYM8mtx.js";import"./chunk-FMBD7UC4-CyCfpT3p.js";import"./chunk-55IACEB6-HURI4nLM.js";import"./chunk-QN33PNHL-BbkJTAOV.js";var p={parser:e,get db(){return new t},renderer:s,styles:a,init:i(r=>{r.class||(r.class={}),r.class.arrowMarkerAbsolute=r.arrowMarkerAbsolute},"init")};export{p as diagram};
@@ -1 +0,0 @@
1
- import{s as a,c as s,a as e,C as t}from"./chunk-B4BG7PRW-rC-ot-Mn.js";import{_ as i}from"./main-doYM8mtx.js";import"./chunk-FMBD7UC4-CyCfpT3p.js";import"./chunk-55IACEB6-HURI4nLM.js";import"./chunk-QN33PNHL-BbkJTAOV.js";var p={parser:e,get db(){return new t},renderer:s,styles:a,init:i(r=>{r.class||(r.class={}),r.class.arrowMarkerAbsolute=r.arrowMarkerAbsolute},"init")};export{p as diagram};
@@ -1 +0,0 @@
1
- import{b as r}from"./_baseUniq-Bk4j3bVH.js";var e=4;function a(o){return r(o,e)}export{a as c};