@buda-ai/connector 0.1.33 → 0.1.34

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.
@@ -258,7 +258,7 @@ For larger apps, create in phases:
258
258
  1. Foundation: scaffold, dependencies, layout, routing
259
259
  2. Core feature: main user journey
260
260
  3. Polish: styling, empty states, errors, responsive behavior
261
- 4. Verification: build/lint/test and browser preview
261
+ 4. Verification: build/lint/test and local browser preview
262
262
  5. Git: commit the slice when the working tree has meaningful changes
263
263
 
264
264
  ### 3. Create or edit files
@@ -327,7 +327,7 @@ If lint is not configured, do not invent a full lint setup unless useful. At min
327
327
 
328
328
  ### 5. Launch a live preview when visual output matters
329
329
 
330
- If the user wants to view, run, preview, open, demo, or inspect the app in a browser, also use the `request_preview_url` tool to output the both a PUBLIC And Local URL
330
+ If the user wants to view, run, preview, open, demo, or inspect the app in a local browser, also use the `request_preview_url` tool to output the both a PUBLIC And Local URL
331
331
 
332
332
  **For static apps, serve `public/` with a zero-dependency static server — do NOT install a dev server or run a package manager.** From the app folder run e.g. `python3 -m http.server <port> --directory public` (or `bunx serve public -l <port>` only if Python is unavailable), then share the URL the same way as below.
333
333
 
@@ -76,11 +76,11 @@ Users want to **see** it running — not read a code block.
76
76
  8. **Never hardcode working directory**. Derive paths relative to the project directory. Do not assume `/agent/` unless that is the actual project root.
77
77
  9. **Support multiple simultaneous dev servers**. PID/log files must be scoped per project (use a hash or sanitized project path), not a single global `/tmp/buda-preview.*`.
78
78
  10. **Read `buda.app.json` first**. If a `buda.app.json` exists in the project directory, read it to get the dev command, port, and other settings before falling back to defaults.
79
+ 11. Do not use AI Browser for sandbox localhost previews unless the user explicitly wants the AI-controlled CDP browser to visit the signed external preview URL.
79
80
 
80
81
  ## AI Browser vs Local Browser
81
82
 
82
83
  - Use this skill and `get_preview_url` when the user wants to preview a local dev server or generated app. Buda opens that preview in **Local Browser**.
83
- - Do not use AI Browser for sandbox localhost previews unless the user explicitly wants the AI-controlled CDP browser to visit the signed external preview URL.
84
84
 
85
85
  ---
86
86
 
package/dist/cli.js CHANGED
@@ -104,8 +104,8 @@ var defaultDependencies = {
104
104
  };
105
105
  var readRawSystemId = (dependencies) => {
106
106
  if (dependencies.platform === "darwin") {
107
- const output = dependencies.execFile("ioreg", ["-rd1", "-c", "IOPlatformExpertDevice"]);
108
- return output.match(/"IOPlatformUUID"\s*=\s*"([^"]+)"/)?.[1];
107
+ const output2 = dependencies.execFile("ioreg", ["-rd1", "-c", "IOPlatformExpertDevice"]);
108
+ return output2.match(/"IOPlatformUUID"\s*=\s*"([^"]+)"/)?.[1];
109
109
  }
110
110
  if (dependencies.platform === "linux") {
111
111
  for (const filePath of ["/etc/machine-id", "/var/lib/dbus/machine-id"]) {
@@ -118,13 +118,13 @@ var readRawSystemId = (dependencies) => {
118
118
  return void 0;
119
119
  }
120
120
  if (dependencies.platform === "win32") {
121
- const output = dependencies.execFile("reg", [
121
+ const output2 = dependencies.execFile("reg", [
122
122
  "query",
123
123
  String.raw`HKLM\SOFTWARE\Microsoft\Cryptography`,
124
124
  "/v",
125
125
  "MachineGuid"
126
126
  ]);
127
- return output.match(/MachineGuid\s+REG_SZ\s+([^\r\n]+)/i)?.[1];
127
+ return output2.match(/MachineGuid\s+REG_SZ\s+([^\r\n]+)/i)?.[1];
128
128
  }
129
129
  return void 0;
130
130
  };
@@ -523,7 +523,7 @@ import path2 from "path";
523
523
  // package.json
524
524
  var package_default = {
525
525
  name: "@buda-ai/connector",
526
- version: "0.1.33",
526
+ version: "0.1.34",
527
527
  private: false,
528
528
  type: "module",
529
529
  publishConfig: {
@@ -550,7 +550,7 @@ var package_default = {
550
550
  "lint:err": "biome format . --write && biome check . --write --diagnostic-level=error"
551
551
  },
552
552
  dependencies: {
553
- "@bunny-agent/daemon": "0.9.58",
553
+ "@bunny-agent/daemon": "0.9.60-beta.1",
554
554
  "@clack/prompts": "^1.0.0",
555
555
  "playwright-core": "^1.52.0",
556
556
  ws: "^8.21.0"
@@ -854,14 +854,14 @@ var openControllingTerminal = () => {
854
854
  try {
855
855
  inputFd = openSync(inputPath, "r");
856
856
  outputFd = openSync(outputPath, "w");
857
- const input = new ReadStream(inputFd);
858
- const output = new WriteStream(outputFd);
857
+ const input2 = new ReadStream(inputFd);
858
+ const output2 = new WriteStream(outputFd);
859
859
  return {
860
- input,
861
- output,
860
+ input: input2,
861
+ output: output2,
862
862
  close: () => {
863
- input.destroy();
864
- output.destroy();
863
+ input2.destroy();
864
+ output2.destroy();
865
865
  }
866
866
  };
867
867
  } catch {
@@ -1012,8 +1012,8 @@ var getConnectorSectionHeight = (state, height) => state.connectors.length ? Mat
1012
1012
  Math.max(4, state.connectors.length + 2),
1013
1013
  Math.max(4, Math.min(Math.floor(height / 3), height - 13))
1014
1014
  ) : 0;
1015
- var parseDashboardMouseWheel = (input, state, size) => {
1016
- const event = input.split("\x1B[<").at(-1);
1015
+ var parseDashboardMouseWheel = (input2, state, size) => {
1016
+ const event = input2.split("\x1B[<").at(-1);
1017
1017
  const match = event?.match(/^(64|65);\d+;(\d+)[Mm]/);
1018
1018
  if (!match) return void 0;
1019
1019
  const row = Number(match[2]);
@@ -1124,13 +1124,13 @@ var renderConnectors = (state, height, width) => {
1124
1124
  const range = state.connectors.length ? `${start + 1}-${start + visible.length}/${state.connectors.length}` : "0/0";
1125
1125
  const title = ` Connectors ${state.activeSection === "connectors" ? "[active]" : ""}`;
1126
1126
  const headerFill = Math.max(1, innerWidth - title.length - range.length);
1127
- const output = [
1127
+ const output2 = [
1128
1128
  `${state.activeSection === "connectors" ? colors.reverse : ""}+${title}${"-".repeat(headerFill)}${range}+${colors.reset}`
1129
1129
  ];
1130
1130
  for (let index = 0; index < contentHeight; index += 1) {
1131
1131
  const connector = visible[index];
1132
1132
  if (!connector) {
1133
- output.push(`|${" ".repeat(innerWidth)}|`);
1133
+ output2.push(`|${" ".repeat(innerWidth)}|`);
1134
1134
  continue;
1135
1135
  }
1136
1136
  const marker = connector.connectorId === state.selectedConnectorId ? ">" : " ";
@@ -1141,10 +1141,10 @@ var renderConnectors = (state, height, width) => {
1141
1141
  const serverWidth = Math.max(8, availableFieldWidth - connectorWidth - spaceWidth);
1142
1142
  const content = `${marker} ${statusText} ${truncate(connector.label ?? connector.connectorId, connectorWidth)} | ${truncate(connector.spaceId, spaceWidth)} | ${truncate(connector.serverUrl, serverWidth)}`;
1143
1143
  const color = connector.status === "Stopped" ? colors.dim : connector.status === "Online" ? colors.cyan : connector.status === "Connecting" || connector.status === "Stopping" ? colors.yellow : connector.status === "Error" || connector.status === "Unresponsive" ? colors.red : "";
1144
- output.push(`|${color}${truncate(content, innerWidth)}${colors.reset}|`);
1144
+ output2.push(`|${color}${truncate(content, innerWidth)}${colors.reset}|`);
1145
1145
  }
1146
- output.push(`+${"-".repeat(innerWidth)}+`);
1147
- return output;
1146
+ output2.push(`+${"-".repeat(innerWidth)}+`);
1147
+ return output2;
1148
1148
  };
1149
1149
  var renderPane = (title, lines, height, width, active, scroll) => {
1150
1150
  const innerWidth = width - 2;
@@ -1154,22 +1154,22 @@ var renderPane = (title, lines, height, width, active, scroll) => {
1154
1154
  const headerSuffix = scroll === 0 ? "following" : `${scroll} lines behind`;
1155
1155
  const titleText = ` ${title} ${active ? "[active]" : ""}`;
1156
1156
  const headerFill = Math.max(1, innerWidth - titleText.length - headerSuffix.length);
1157
- const output = [
1157
+ const output2 = [
1158
1158
  `${active ? colors.reverse : ""}+${titleText}${"-".repeat(headerFill)}${headerSuffix}+${colors.reset}`
1159
1159
  ];
1160
1160
  for (let index = 0; index < contentHeight; index += 1) {
1161
1161
  const line = visible[index];
1162
1162
  if (!line) {
1163
- output.push(`|${" ".repeat(innerWidth)}|`);
1163
+ output2.push(`|${" ".repeat(innerWidth)}|`);
1164
1164
  continue;
1165
1165
  }
1166
1166
  const levelColor = line.level === "error" ? colors.red : line.level === "warn" ? colors.yellow : colors.dim;
1167
1167
  const count = line.count > 1 ? ` x${line.count}` : "";
1168
1168
  const content = `${line.time} ${line.level.toUpperCase().padEnd(5)} ${line.message}${count}`;
1169
- output.push(`|${levelColor}${truncate(content, innerWidth)}${colors.reset}|`);
1169
+ output2.push(`|${levelColor}${truncate(content, innerWidth)}${colors.reset}|`);
1170
1170
  }
1171
- output.push(`+${"-".repeat(innerWidth)}+`);
1172
- return output;
1171
+ output2.push(`+${"-".repeat(innerWidth)}+`);
1172
+ return output2;
1173
1173
  };
1174
1174
  var renderFooter = (state, width) => {
1175
1175
  const managerKeys = state.connectors.length ? "Up/Down select | S stop | Esc exit | " : "";
@@ -1531,7 +1531,7 @@ var installConnectorConsoleCapture = () => {
1531
1531
  log: console.log,
1532
1532
  warn: console.warn
1533
1533
  };
1534
- const capture = (level, output) => (...args) => {
1534
+ const capture = (level, output2) => (...args) => {
1535
1535
  const message = format2(...args);
1536
1536
  if (!message.startsWith("[buda-connector]")) {
1537
1537
  writes.push(
@@ -1546,7 +1546,7 @@ var installConnectorConsoleCapture = () => {
1546
1546
  })
1547
1547
  );
1548
1548
  }
1549
- output(...args);
1549
+ output2(...args);
1550
1550
  };
1551
1551
  console.log = capture("info", original.log);
1552
1552
  console.warn = capture("warn", original.warn);
@@ -1824,7 +1824,7 @@ async function handleBrowserInput(sessionIdValue, body) {
1824
1824
  if (!sessionId) throw new Error("A valid browser session id is required.");
1825
1825
  const ev = body ?? {};
1826
1826
  const s = await ensureSession(sessionId);
1827
- const input = s.inputQueue.catch(() => {
1827
+ const input2 = s.inputQueue.catch(() => {
1828
1828
  }).then(async () => {
1829
1829
  switch (ev.type) {
1830
1830
  case "mouseMove":
@@ -1878,8 +1878,8 @@ async function handleBrowserInput(sessionIdValue, body) {
1878
1878
  throw new Error(`Unknown browser input event: ${String(ev.type)}`);
1879
1879
  }
1880
1880
  });
1881
- s.inputQueue = input;
1882
- await input;
1881
+ s.inputQueue = input2;
1882
+ await input2;
1883
1883
  }
1884
1884
  var getPageResult = async (s) => ({
1885
1885
  url: s.page.url(),
@@ -1909,16 +1909,16 @@ async function handleBrowserRequest(requestPath, method, body, context = {}) {
1909
1909
  if (!sessionId)
1910
1910
  return jsonResponse(400, { ok: false, error: "valid browser session id required" });
1911
1911
  if (route === "start" && method === "POST") {
1912
- const input = body ?? {};
1912
+ const input2 = body ?? {};
1913
1913
  const viewport = {
1914
- width: normalizeViewportDimension(input.width, 320, 2560, DEFAULT_VIEWPORT.width),
1915
- height: normalizeViewportDimension(input.height, 240, 2560, DEFAULT_VIEWPORT.height)
1914
+ width: normalizeViewportDimension(input2.width, 320, 2560, DEFAULT_VIEWPORT.width),
1915
+ height: normalizeViewportDimension(input2.height, 240, 2560, DEFAULT_VIEWPORT.height)
1916
1916
  };
1917
1917
  const s = await ensureSession(sessionId, viewport);
1918
- const clientId = normalizeSessionId(input.clientId);
1918
+ const clientId = normalizeSessionId(input2.clientId);
1919
1919
  if (clientId) s.clientIds.add(clientId);
1920
1920
  await resizeBrowser(s, viewport);
1921
- const url = input.url?.trim() || "about:blank";
1921
+ const url = input2.url?.trim() || "about:blank";
1922
1922
  await writeLog("info", `browser viewport ${viewport.width}x${viewport.height}`);
1923
1923
  await navigateBrowser(s, url);
1924
1924
  await writeLog("info", `browser ready at ${s.page.url()}`);
@@ -1929,8 +1929,8 @@ async function handleBrowserRequest(requestPath, method, body, context = {}) {
1929
1929
  return jsonResponse(200, { ok: true });
1930
1930
  }
1931
1931
  if (route === "release" && method === "POST") {
1932
- const input = body ?? {};
1933
- const clientId = normalizeSessionId(input.clientId);
1932
+ const input2 = body ?? {};
1933
+ const clientId = normalizeSessionId(input2.clientId);
1934
1934
  if (!clientId) return jsonResponse(400, { ok: false, error: "valid client id required" });
1935
1935
  const s = sessions.get(sessionId);
1936
1936
  if (!s) return jsonResponse(200, { ok: true, closed: false });
@@ -1940,13 +1940,13 @@ async function handleBrowserRequest(requestPath, method, body, context = {}) {
1940
1940
  return jsonResponse(200, { ok: true, closed: true });
1941
1941
  }
1942
1942
  if (route === "navigate" && method === "POST") {
1943
- const input = body ?? {};
1944
- const url = input.url?.trim();
1943
+ const input2 = body ?? {};
1944
+ const url = input2.url?.trim();
1945
1945
  if (!url) return jsonResponse(400, { ok: false, error: "url required" });
1946
1946
  const s = await ensureSession(sessionId);
1947
1947
  const response = await navigateBrowser(s, url, {
1948
- waitUntil: input.waitUntil ?? "domcontentloaded",
1949
- timeout: normalizeTimeout(input.timeoutMs, 3e4, 6e4)
1948
+ waitUntil: input2.waitUntil ?? "domcontentloaded",
1949
+ timeout: normalizeTimeout(input2.timeoutMs, 3e4, 6e4)
1950
1950
  });
1951
1951
  return jsonResponse(200, {
1952
1952
  ok: true,
@@ -1956,14 +1956,14 @@ async function handleBrowserRequest(requestPath, method, body, context = {}) {
1956
1956
  });
1957
1957
  }
1958
1958
  if (route === "click" && method === "POST") {
1959
- const input = body ?? {};
1960
- const selector = input.selector?.trim();
1959
+ const input2 = body ?? {};
1960
+ const selector = input2.selector?.trim();
1961
1961
  if (!selector) return jsonResponse(400, { ok: false, error: "selector required" });
1962
1962
  const s = await ensureSession(sessionId);
1963
- const button = input.button === "right" || input.button === "middle" ? input.button : "left";
1963
+ const button = input2.button === "right" || input2.button === "middle" ? input2.button : "left";
1964
1964
  await s.page.locator(selector).click({
1965
1965
  button,
1966
- timeout: normalizeTimeout(input.timeoutMs, 1e4, 3e4)
1966
+ timeout: normalizeTimeout(input2.timeoutMs, 1e4, 3e4)
1967
1967
  });
1968
1968
  await s.page.waitForLoadState("domcontentloaded", { timeout: 5e3 }).catch(() => {
1969
1969
  });
@@ -1975,14 +1975,14 @@ async function handleBrowserRequest(requestPath, method, body, context = {}) {
1975
1975
  });
1976
1976
  }
1977
1977
  if (route === "type" && method === "POST") {
1978
- const input = body ?? {};
1979
- const selector = input.selector?.trim();
1978
+ const input2 = body ?? {};
1979
+ const selector = input2.selector?.trim();
1980
1980
  if (!selector) return jsonResponse(400, { ok: false, error: "selector required" });
1981
1981
  const s = await ensureSession(sessionId);
1982
1982
  const locator = s.page.locator(selector);
1983
- const text2 = typeof input.text === "string" ? input.text : String(input.text ?? "");
1984
- const timeout = normalizeTimeout(input.timeoutMs, 1e4, 3e4);
1985
- if (input.clear !== false) {
1983
+ const text2 = typeof input2.text === "string" ? input2.text : String(input2.text ?? "");
1984
+ const timeout = normalizeTimeout(input2.timeoutMs, 1e4, 3e4);
1985
+ if (input2.clear !== false) {
1986
1986
  await locator.fill("", { timeout });
1987
1987
  await locator.fill(text2, { timeout });
1988
1988
  } else {
@@ -1996,12 +1996,12 @@ async function handleBrowserRequest(requestPath, method, body, context = {}) {
1996
1996
  });
1997
1997
  }
1998
1998
  if (route === "extract" && method === "POST") {
1999
- const input = body ?? {};
2000
- const selector = input.selector?.trim() || "body";
1999
+ const input2 = body ?? {};
2000
+ const selector = input2.selector?.trim() || "body";
2001
2001
  const s = await ensureSession(sessionId);
2002
2002
  const locator = s.page.locator(selector).first();
2003
2003
  const text2 = (await locator.innerText({ timeout: 1e4 }).catch(async () => s.page.locator("body").innerText({ timeout: 1e4 }))).trim();
2004
- const maxChars = typeof input.maxChars === "number" && Number.isFinite(input.maxChars) ? Math.min(2e4, Math.max(500, Math.round(input.maxChars))) : 8e3;
2004
+ const maxChars = typeof input2.maxChars === "number" && Number.isFinite(input2.maxChars) ? Math.min(2e4, Math.max(500, Math.round(input2.maxChars))) : 8e3;
2005
2005
  return jsonResponse(200, {
2006
2006
  ok: true,
2007
2007
  action: "extract",
@@ -2010,13 +2010,13 @@ async function handleBrowserRequest(requestPath, method, body, context = {}) {
2010
2010
  });
2011
2011
  }
2012
2012
  if (route === "screenshot" && method === "POST") {
2013
- const input = body ?? {};
2013
+ const input2 = body ?? {};
2014
2014
  const s = await ensureSession(sessionId);
2015
- const screenshotPath = resolveScreenshotPath(context.workdirRoot, input.file_path);
2015
+ const screenshotPath = resolveScreenshotPath(context.workdirRoot, input2.file_path);
2016
2016
  await mkdir4(path4.dirname(screenshotPath.absolutePath), { recursive: true });
2017
2017
  await s.page.screenshot({
2018
2018
  path: screenshotPath.absolutePath,
2019
- fullPage: input.fullPage !== false
2019
+ fullPage: input2.fullPage !== false
2020
2020
  });
2021
2021
  return jsonResponse(200, {
2022
2022
  ok: true,
@@ -2027,10 +2027,10 @@ async function handleBrowserRequest(requestPath, method, body, context = {}) {
2027
2027
  });
2028
2028
  }
2029
2029
  if (route === "resize" && method === "POST") {
2030
- const input = body ?? {};
2030
+ const input2 = body ?? {};
2031
2031
  const viewport = {
2032
- width: normalizeViewportDimension(input.width, 320, 2560, DEFAULT_VIEWPORT.width),
2033
- height: normalizeViewportDimension(input.height, 240, 2560, DEFAULT_VIEWPORT.height)
2032
+ width: normalizeViewportDimension(input2.width, 320, 2560, DEFAULT_VIEWPORT.width),
2033
+ height: normalizeViewportDimension(input2.height, 240, 2560, DEFAULT_VIEWPORT.height)
2034
2034
  };
2035
2035
  const s = await ensureSession(sessionId);
2036
2036
  await resizeBrowser(s, viewport);
@@ -2981,15 +2981,15 @@ var streamDaemonLogs = (options) => {
2981
2981
  if (!shouldDisplayConnectorLogEntry(entry.createdAt, options.startedAt)) continue;
2982
2982
  const connectorId = entry.metadata?.connectorId;
2983
2983
  if (options.dashboardActive && typeof connectorId === "string") {
2984
- const output2 = entry.metadata?.source === "daemon-console" ? entry.message : `[buda-connector] ${entry.message}`;
2985
- appendConnectorDashboardLog(connectorId, entry.level, output2);
2984
+ const output3 = entry.metadata?.source === "daemon-console" ? entry.message : `[buda-connector] ${entry.message}`;
2985
+ appendConnectorDashboardLog(connectorId, entry.level, output3);
2986
2986
  continue;
2987
2987
  }
2988
2988
  if (connectorId !== options.connectorId) continue;
2989
- const output = entry.metadata?.source === "daemon-console" ? entry.message : `[buda-connector] ${entry.message}`;
2990
- if (entry.level === "error") console.error(output);
2991
- else if (entry.level === "warn") console.warn(output);
2992
- else console.log(output);
2989
+ const output2 = entry.metadata?.source === "daemon-console" ? entry.message : `[buda-connector] ${entry.message}`;
2990
+ if (entry.level === "error") console.error(output2);
2991
+ else if (entry.level === "warn") console.warn(output2);
2992
+ else console.log(output2);
2993
2993
  } catch {
2994
2994
  if (options.plain) console.log(line);
2995
2995
  }
@@ -3230,9 +3230,6 @@ var getDaemonModeFlag = () => {
3230
3230
  return process.argv[index + 1] === "transient" ? "transient" : "persistent";
3231
3231
  };
3232
3232
 
3233
- // src/onboard.ts
3234
- import { cancel, intro, isCancel, log, note, outro, spinner, text } from "@clack/prompts";
3235
-
3236
3233
  // src/bunny-daemon.ts
3237
3234
  import { mkdir as mkdir7 } from "fs/promises";
3238
3235
  import { createDaemon } from "@bunny-agent/daemon";
@@ -3471,17 +3468,17 @@ var installConnectorTerminalEndpoint = (server, options = {}) => {
3471
3468
  sessions2.clear();
3472
3469
  });
3473
3470
  };
3474
- var registerLocalTerminal = (input) => {
3475
- if (!isSafeId(input.workspaceKey) || !isSafeId(input.tabId)) {
3471
+ var registerLocalTerminal = (input2) => {
3472
+ if (!isSafeId(input2.workspaceKey) || !isSafeId(input2.tabId)) {
3476
3473
  throw new Error("Invalid local terminal workspace session.");
3477
3474
  }
3478
3475
  const token = randomBytes3(32).toString("base64url");
3479
3476
  localGrants.set(token, {
3480
- sessionKey: `${input.workspaceKey}:${input.tabId}`,
3481
- workspaceKey: input.workspaceKey,
3482
- cwd: input.cwd,
3483
- cols: input.cols,
3484
- rows: input.rows,
3477
+ sessionKey: `${input2.workspaceKey}:${input2.tabId}`,
3478
+ workspaceKey: input2.workspaceKey,
3479
+ cwd: input2.cwd,
3480
+ cols: input2.cols,
3481
+ rows: input2.rows,
3485
3482
  expiresAt: Date.now() + LOCAL_TERMINAL_GRANT_TTL_MS
3486
3483
  });
3487
3484
  const cleanupTimer = setTimeout(() => localGrants.delete(token), LOCAL_TERMINAL_GRANT_TTL_MS);
@@ -3505,16 +3502,16 @@ var connectSocket = async (socket) => new Promise((resolve, reject) => {
3505
3502
  socket.once("open", onOpen);
3506
3503
  socket.once("error", onError);
3507
3504
  });
3508
- var proxyConnectorTerminalTunnel = async (input) => {
3505
+ var proxyConnectorTerminalTunnel = async (input2) => {
3509
3506
  const cloud = new WebSocket(
3510
- getConnectorTerminalUrl(input.serverUrl, input.connectorId, input.sessionId),
3507
+ getConnectorTerminalUrl(input2.serverUrl, input2.connectorId, input2.sessionId),
3511
3508
  {
3512
- headers: { "X-Buda-Terminal-Token": input.cloudToken },
3509
+ headers: { "X-Buda-Terminal-Token": input2.cloudToken },
3513
3510
  handshakeTimeout: TERMINAL_HANDSHAKE_TIMEOUT_MS
3514
3511
  }
3515
3512
  );
3516
- const local = new WebSocket(toLocalTerminalUrl(input.localBaseUrl), {
3517
- headers: { "X-Buda-Local-Terminal-Token": input.localToken },
3513
+ const local = new WebSocket(toLocalTerminalUrl(input2.localBaseUrl), {
3514
+ headers: { "X-Buda-Local-Terminal-Token": input2.localToken },
3518
3515
  handshakeTimeout: TERMINAL_HANDSHAKE_TIMEOUT_MS
3519
3516
  });
3520
3517
  let bridgeAccepted = false;
@@ -3525,7 +3522,7 @@ var proxyConnectorTerminalTunnel = async (input) => {
3525
3522
  const endActivity = () => {
3526
3523
  if (!activityStarted || activityEnded) return;
3527
3524
  activityEnded = true;
3528
- input.onActivityEnd?.();
3525
+ input2.onActivityEnd?.();
3529
3526
  };
3530
3527
  let pendingBytes = 0;
3531
3528
  const pendingCloudFrames = [];
@@ -3581,7 +3578,7 @@ var proxyConnectorTerminalTunnel = async (input) => {
3581
3578
  if (!bridgeAccepted) {
3582
3579
  void writeLog(
3583
3580
  "warn",
3584
- `terminal cloud tunnel closed before readiness session=${input.sessionId} code=${code} reason=${normalizedReason}`
3581
+ `terminal cloud tunnel closed before readiness session=${input2.sessionId} code=${code} reason=${normalizedReason}`
3585
3582
  );
3586
3583
  }
3587
3584
  if (local.readyState === WebSocket.OPEN) {
@@ -3619,12 +3616,12 @@ var proxyConnectorTerminalTunnel = async (input) => {
3619
3616
  if (cloud.readyState !== WebSocket.OPEN) return;
3620
3617
  if (local.readyState === WebSocket.OPEN) {
3621
3618
  activityStarted = true;
3622
- input.onActivityStart?.();
3619
+ input2.onActivityStart?.();
3623
3620
  }
3624
3621
  cloud.send(JSON.stringify({ type: "bridge-ready" }));
3625
3622
  await writeLog(
3626
3623
  "info",
3627
- `terminal proxy connected session=${input.sessionId} workspace=${input.workspaceKey}`
3624
+ `terminal proxy connected session=${input2.sessionId} workspace=${input2.workspaceKey}`
3628
3625
  );
3629
3626
  };
3630
3627
 
@@ -4208,6 +4205,86 @@ var verifyFailure = (detail) => new LegacyWorkspaceMigrationError(
4208
4205
  var corrupt = (message) => new LegacyWorkspaceMigrationError("MIGRATION_CORRUPT", message);
4209
4206
  var errorMessage = (error) => error instanceof Error ? error.message : String(error);
4210
4207
 
4208
+ // src/prompts.ts
4209
+ import { stdin as input, stdout as output } from "process";
4210
+ import { createInterface } from "readline/promises";
4211
+ var CANCELLED = /* @__PURE__ */ Symbol("prompt-cancelled");
4212
+ function printLine(prefix, message) {
4213
+ output.write(`${prefix}${message}
4214
+ `);
4215
+ }
4216
+ function intro(message) {
4217
+ printLine("\n", message);
4218
+ }
4219
+ function outro(message) {
4220
+ printLine("", message);
4221
+ }
4222
+ function cancel(message) {
4223
+ printLine("", message);
4224
+ }
4225
+ function note(message, title) {
4226
+ if (title) {
4227
+ printLine("", `${title}
4228
+ ${message}`);
4229
+ return;
4230
+ }
4231
+ printLine("", message);
4232
+ }
4233
+ var log = {
4234
+ info(message) {
4235
+ printLine("", message);
4236
+ },
4237
+ error(message) {
4238
+ printLine("", message);
4239
+ },
4240
+ step(message) {
4241
+ printLine("", message);
4242
+ }
4243
+ };
4244
+ function isCancel(value) {
4245
+ return value === CANCELLED;
4246
+ }
4247
+ function spinner() {
4248
+ let activeMessage = null;
4249
+ return {
4250
+ start(message) {
4251
+ activeMessage = message;
4252
+ printLine("", message);
4253
+ },
4254
+ stop(message) {
4255
+ if (message) {
4256
+ printLine("", message);
4257
+ } else if (activeMessage) {
4258
+ printLine("", activeMessage);
4259
+ }
4260
+ activeMessage = null;
4261
+ }
4262
+ };
4263
+ }
4264
+ async function text(options) {
4265
+ if (!input.isTTY || !output.isTTY) {
4266
+ const fallback = options.defaultValue ?? "";
4267
+ const validationError = options.validate?.(fallback);
4268
+ return validationError ? CANCELLED : fallback;
4269
+ }
4270
+ const rl = createInterface({ input, output });
4271
+ const hint = options.defaultValue ?? options.placeholder;
4272
+ const suffix = hint ? ` (${hint})` : "";
4273
+ try {
4274
+ while (true) {
4275
+ const answer = await rl.question(`${options.message}${suffix}: `);
4276
+ const value = answer.trim() || options.defaultValue || "";
4277
+ const validationError = options.validate?.(value);
4278
+ if (!validationError) return value;
4279
+ printLine("", validationError);
4280
+ }
4281
+ } catch {
4282
+ return CANCELLED;
4283
+ } finally {
4284
+ rl.close();
4285
+ }
4286
+ }
4287
+
4211
4288
  // src/relay.ts
4212
4289
  import { realpathSync } from "fs";
4213
4290
  import path12 from "path";
@@ -4298,7 +4375,10 @@ function verifyConnectorExecutionIdentity(options) {
4298
4375
  const signature = decodeSignature(identity.signature);
4299
4376
  let verified = false;
4300
4377
  try {
4301
- const publicKey = createPublicKey({ key: protocol.publicKeyJwk, format: "jwk" });
4378
+ const publicKey = createPublicKey({
4379
+ key: protocol.publicKeyJwk,
4380
+ format: "jwk"
4381
+ });
4302
4382
  if (publicKey.asymmetricKeyType !== "ed25519") {
4303
4383
  throw new ConnectorRelayProtocolError("PROTOCOL_UNSUPPORTED");
4304
4384
  }
@@ -4405,8 +4485,8 @@ var MIME_TYPES = {
4405
4485
  };
4406
4486
  var HtmlPreviewServerRegistry = class {
4407
4487
  servers = /* @__PURE__ */ new Map();
4408
- async open(input) {
4409
- const htmlFile = await resolveWorkspaceFile(input);
4488
+ async open(input2) {
4489
+ const htmlFile = await resolveWorkspaceFile(input2);
4410
4490
  const folder = path10.dirname(htmlFile);
4411
4491
  let pending = this.servers.get(folder);
4412
4492
  if (!pending) {
@@ -4464,10 +4544,10 @@ var handleHtmlPreviewRequest = async (request, mounts, registry) => {
4464
4544
  );
4465
4545
  }
4466
4546
  };
4467
- var resolveWorkspaceFile = async (input) => {
4468
- const virtualPath = input.filePath.replaceAll("\\", "/");
4547
+ var resolveWorkspaceFile = async (input2) => {
4548
+ const virtualPath = input2.filePath.replaceAll("\\", "/");
4469
4549
  if (virtualPath.includes("\0")) throw new Error("HTML preview path contains invalid data.");
4470
- const mountPath = path10.resolve(input.mounts[input.rootVolume]);
4550
+ const mountPath = path10.resolve(input2.mounts[input2.rootVolume]);
4471
4551
  const root = await realpath3(mountPath);
4472
4552
  let relativePath = virtualPath;
4473
4553
  let explicitVolume;
@@ -4479,7 +4559,7 @@ var resolveWorkspaceFile = async (input) => {
4479
4559
  break;
4480
4560
  }
4481
4561
  }
4482
- if (explicitVolume && explicitVolume !== input.rootVolume) {
4562
+ if (explicitVolume && explicitVolume !== input2.rootVolume) {
4483
4563
  throw new Error("HTML preview path does not match the requested root volume.");
4484
4564
  }
4485
4565
  if (!explicitVolume && (path10.isAbsolute(virtualPath) || /^[A-Za-z]:\//.test(virtualPath))) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@buda-ai/connector",
3
- "version": "0.1.33",
3
+ "version": "0.1.34",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "publishConfig": {
@@ -27,7 +27,7 @@
27
27
  "lint:err": "biome format . --write && biome check . --write --diagnostic-level=error"
28
28
  },
29
29
  "dependencies": {
30
- "@bunny-agent/daemon": "0.9.58",
30
+ "@bunny-agent/daemon": "0.9.60-beta.1",
31
31
  "@clack/prompts": "^1.0.0",
32
32
  "playwright-core": "^1.52.0",
33
33
  "ws": "^8.21.0"