@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
|
|
108
|
-
return
|
|
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
|
|
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
|
|
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.
|
|
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.
|
|
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
|
|
858
|
-
const
|
|
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
|
-
|
|
864
|
-
|
|
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 = (
|
|
1016
|
-
const event =
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
1144
|
+
output2.push(`|${color}${truncate(content, innerWidth)}${colors.reset}|`);
|
|
1145
1145
|
}
|
|
1146
|
-
|
|
1147
|
-
return
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
1169
|
+
output2.push(`|${levelColor}${truncate(content, innerWidth)}${colors.reset}|`);
|
|
1170
1170
|
}
|
|
1171
|
-
|
|
1172
|
-
return
|
|
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,
|
|
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
|
-
|
|
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
|
|
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 =
|
|
1882
|
-
await
|
|
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
|
|
1912
|
+
const input2 = body ?? {};
|
|
1913
1913
|
const viewport = {
|
|
1914
|
-
width: normalizeViewportDimension(
|
|
1915
|
-
height: normalizeViewportDimension(
|
|
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(
|
|
1918
|
+
const clientId = normalizeSessionId(input2.clientId);
|
|
1919
1919
|
if (clientId) s.clientIds.add(clientId);
|
|
1920
1920
|
await resizeBrowser(s, viewport);
|
|
1921
|
-
const url =
|
|
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
|
|
1933
|
-
const clientId = normalizeSessionId(
|
|
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
|
|
1944
|
-
const url =
|
|
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:
|
|
1949
|
-
timeout: normalizeTimeout(
|
|
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
|
|
1960
|
-
const selector =
|
|
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 =
|
|
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(
|
|
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
|
|
1979
|
-
const selector =
|
|
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
|
|
1984
|
-
const timeout = normalizeTimeout(
|
|
1985
|
-
if (
|
|
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
|
|
2000
|
-
const selector =
|
|
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
|
|
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
|
|
2013
|
+
const input2 = body ?? {};
|
|
2014
2014
|
const s = await ensureSession(sessionId);
|
|
2015
|
-
const screenshotPath = resolveScreenshotPath(context.workdirRoot,
|
|
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:
|
|
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
|
|
2030
|
+
const input2 = body ?? {};
|
|
2031
2031
|
const viewport = {
|
|
2032
|
-
width: normalizeViewportDimension(
|
|
2033
|
-
height: normalizeViewportDimension(
|
|
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
|
|
2985
|
-
appendConnectorDashboardLog(connectorId, entry.level,
|
|
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
|
|
2990
|
-
if (entry.level === "error") console.error(
|
|
2991
|
-
else if (entry.level === "warn") console.warn(
|
|
2992
|
-
else console.log(
|
|
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 = (
|
|
3475
|
-
if (!isSafeId(
|
|
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: `${
|
|
3481
|
-
workspaceKey:
|
|
3482
|
-
cwd:
|
|
3483
|
-
cols:
|
|
3484
|
-
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 (
|
|
3505
|
+
var proxyConnectorTerminalTunnel = async (input2) => {
|
|
3509
3506
|
const cloud = new WebSocket(
|
|
3510
|
-
getConnectorTerminalUrl(
|
|
3507
|
+
getConnectorTerminalUrl(input2.serverUrl, input2.connectorId, input2.sessionId),
|
|
3511
3508
|
{
|
|
3512
|
-
headers: { "X-Buda-Terminal-Token":
|
|
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(
|
|
3517
|
-
headers: { "X-Buda-Local-Terminal-Token":
|
|
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
|
-
|
|
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=${
|
|
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
|
-
|
|
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=${
|
|
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({
|
|
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(
|
|
4409
|
-
const htmlFile = await resolveWorkspaceFile(
|
|
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 (
|
|
4468
|
-
const virtualPath =
|
|
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(
|
|
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 !==
|
|
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.
|
|
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.
|
|
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"
|