open-agents-ai 0.187.136 → 0.187.138

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 (2) hide show
  1. package/dist/index.js +693 -192
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -247838,9 +247838,9 @@ var init_vision = __esm({
247838
247838
  if (ollamaResult)
247839
247839
  return ollamaResult;
247840
247840
  try {
247841
- const { execSync: execSync46 } = await import("node:child_process");
247841
+ const { execSync: execSync48 } = await import("node:child_process");
247842
247842
  try {
247843
- execSync46("pip3 install --user moondream 2>/dev/null || pip install --user moondream 2>/dev/null", {
247843
+ execSync48("pip3 install --user moondream 2>/dev/null || pip install --user moondream 2>/dev/null", {
247844
247844
  timeout: 12e4,
247845
247845
  stdio: "pipe"
247846
247846
  });
@@ -247853,7 +247853,7 @@ var init_vision = __esm({
247853
247853
  } catch {
247854
247854
  }
247855
247855
  try {
247856
- execSync46("ollama pull moondream", { timeout: 3e5, stdio: "pipe" });
247856
+ execSync48("ollama pull moondream", { timeout: 3e5, stdio: "pipe" });
247857
247857
  const retryOllama = await this.tryOllamaVision(buffer2, filename, action, prompt, length4, start2);
247858
247858
  if (retryOllama)
247859
247859
  return retryOllama;
@@ -247961,8 +247961,8 @@ Coordinates are normalized (0-1). Multiply by image width/height for pixel value
247961
247961
  const errText = await res.text().catch(() => "");
247962
247962
  if (res.status === 404 || /not found|does not exist/i.test(errText)) {
247963
247963
  try {
247964
- const { execSync: execSync46 } = await import("node:child_process");
247965
- execSync46("ollama pull moondream", { timeout: 3e5, stdio: "pipe" });
247964
+ const { execSync: execSync48 } = await import("node:child_process");
247965
+ execSync48("ollama pull moondream", { timeout: 3e5, stdio: "pipe" });
247966
247966
  res = await fetch(`${ollamaHost}/api/generate`, {
247967
247967
  method: "POST",
247968
247968
  headers: { "Content-Type": "application/json" },
@@ -254210,10 +254210,14 @@ ${cameras.join("\n")}`,
254210
254210
  }
254211
254211
  let ssid = null;
254212
254212
  try {
254213
+ try {
254214
+ execSync27("nmcli device wifi rescan 2>/dev/null", { timeout: 5e3, stdio: "pipe" });
254215
+ } catch {
254216
+ }
254213
254217
  const wifiList = execSync27("nmcli device wifi list 2>/dev/null", { encoding: "utf8", timeout: 1e4 });
254214
- const oscMatch = wifiList.match(/\b(QooCam[^\s]*\.OSC)\b/i);
254218
+ const oscMatch = wifiList.match(/(QooCam[^\n]*?\.OSC)\s/i);
254215
254219
  if (oscMatch)
254216
- ssid = oscMatch[1];
254220
+ ssid = oscMatch[1].trim();
254217
254221
  } catch {
254218
254222
  }
254219
254223
  let connected = false;
@@ -254269,7 +254273,7 @@ ${cameras.join("\n")}`,
254269
254273
  execSync27("nmcli device wifi rescan 2>/dev/null", { timeout: 5e3, stdio: "pipe" });
254270
254274
  execSync27("sleep 2", { timeout: 5e3 });
254271
254275
  const wifiList = execSync27("nmcli device wifi list 2>/dev/null", { encoding: "utf8", timeout: 1e4 });
254272
- const oscMatch = wifiList.match(/\b(QooCam[^\s]*\.OSC)\b/i);
254276
+ const oscMatch = wifiList.match(/(QooCam[^\n]*?\.OSC)\s/i);
254273
254277
  if (oscMatch)
254274
254278
  ssid = oscMatch[1];
254275
254279
  } catch {
@@ -254884,6 +254888,497 @@ ${devices.join("\n")}`,
254884
254888
  }
254885
254889
  });
254886
254890
 
254891
+ // packages/execution/dist/tools/wifi-control.js
254892
+ import { execSync as execSync30 } from "node:child_process";
254893
+ var WifiControlTool;
254894
+ var init_wifi_control = __esm({
254895
+ "packages/execution/dist/tools/wifi-control.js"() {
254896
+ "use strict";
254897
+ WifiControlTool = class {
254898
+ name = "wifi_control";
254899
+ description = "Scan, connect, and manage WiFi networks. Actions: 'scan' to discover nearby networks, 'interfaces' to list WiFi adapters, 'connect' to join a network, 'disconnect' to leave, 'status' for current connection info, 'monitor' to toggle monitor mode on an adapter. Use this to explore the wireless environment, find networks, check signal strength, connect to specific networks, or manage multiple WiFi adapters.";
254900
+ parameters = {
254901
+ type: "object",
254902
+ properties: {
254903
+ action: {
254904
+ type: "string",
254905
+ enum: ["scan", "interfaces", "connect", "disconnect", "status", "monitor"],
254906
+ description: "Action to perform"
254907
+ },
254908
+ ssid: {
254909
+ type: "string",
254910
+ description: "WiFi network name (for 'connect' action)"
254911
+ },
254912
+ password: {
254913
+ type: "string",
254914
+ description: "WiFi password (for 'connect' action)"
254915
+ },
254916
+ interface: {
254917
+ type: "string",
254918
+ description: "WiFi interface name (e.g. wlp69s0, wlan1). Default: auto-detect."
254919
+ },
254920
+ enable: {
254921
+ type: "boolean",
254922
+ description: "true to enable, false to disable (for 'monitor' action)"
254923
+ }
254924
+ },
254925
+ required: ["action"]
254926
+ };
254927
+ async execute(args) {
254928
+ const action = args["action"];
254929
+ const start2 = performance.now();
254930
+ try {
254931
+ switch (action) {
254932
+ case "scan":
254933
+ return this.scanNetworks(args, start2);
254934
+ case "interfaces":
254935
+ return this.listInterfaces(start2);
254936
+ case "connect":
254937
+ return this.connectNetwork(args, start2);
254938
+ case "disconnect":
254939
+ return this.disconnectNetwork(args, start2);
254940
+ case "status":
254941
+ return this.connectionStatus(args, start2);
254942
+ case "monitor":
254943
+ return this.monitorMode(args, start2);
254944
+ default:
254945
+ return { success: false, output: "", error: `Unknown action: ${action}`, durationMs: performance.now() - start2 };
254946
+ }
254947
+ } catch (err) {
254948
+ return { success: false, output: "", error: `wifi_control error: ${err instanceof Error ? err.message : String(err)}`, durationMs: performance.now() - start2 };
254949
+ }
254950
+ }
254951
+ // =========================================================================
254952
+ // Scan nearby WiFi networks
254953
+ // =========================================================================
254954
+ scanNetworks(args, start2) {
254955
+ const iface = args["interface"] || this.findWifiInterface();
254956
+ if (!iface) {
254957
+ return { success: false, output: "", error: "No WiFi interface found. Connect a WiFi adapter.", durationMs: performance.now() - start2 };
254958
+ }
254959
+ try {
254960
+ execSync30(`nmcli device wifi rescan ifname ${iface} 2>/dev/null`, { timeout: 1e4, stdio: "pipe" });
254961
+ execSync30("sleep 1", { timeout: 5e3 });
254962
+ } catch {
254963
+ }
254964
+ try {
254965
+ const raw = execSync30(`nmcli -t -f BSSID,SSID,MODE,CHAN,FREQ,RATE,SIGNAL,BARS,SECURITY,IN-USE device wifi list ifname ${iface} 2>/dev/null`, { encoding: "utf8", timeout: 15e3 });
254966
+ const networks = [];
254967
+ for (const line of raw.trim().split("\n").filter(Boolean)) {
254968
+ const parts = line.split(":");
254969
+ if (parts.length < 9)
254970
+ continue;
254971
+ const bssid = parts.slice(0, 6).join(":");
254972
+ const rest = parts.slice(6);
254973
+ if (rest.length < 9)
254974
+ continue;
254975
+ const ssid = rest[0] || "(hidden)";
254976
+ const channel = parseInt(rest[2] || "0");
254977
+ const frequency = rest[3] || "";
254978
+ const rate = rest[4] || "";
254979
+ const signal = parseInt(rest[5] || "0");
254980
+ const bars = rest[6] || "";
254981
+ const security = rest[7] || "Open";
254982
+ const active = rest[8] === "*";
254983
+ networks.push({ ssid, bssid, channel, frequency, signal, bars, security, rate, active });
254984
+ }
254985
+ if (networks.length === 0) {
254986
+ return { success: true, output: `No WiFi networks found on ${iface}. The adapter may be disabled or out of range.`, durationMs: performance.now() - start2 };
254987
+ }
254988
+ networks.sort((a2, b) => b.signal - a2.signal);
254989
+ const lines = networks.map((n2) => {
254990
+ const marker = n2.active ? " *" : " ";
254991
+ return `${marker}${n2.signal}% ${n2.bars} ${n2.ssid.padEnd(25)} Ch${String(n2.channel).padEnd(3)} ${n2.security.padEnd(12)} ${n2.rate} (${n2.bssid})`;
254992
+ });
254993
+ return {
254994
+ success: true,
254995
+ output: `WiFi networks on ${iface} (${networks.length} found, sorted by signal):
254996
+ ${" Sig".padEnd(5)} ${"".padEnd(5)} ${"SSID".padEnd(25)} ${"Ch".padEnd(4)} ${"Security".padEnd(12)} Rate
254997
+ ${"-".repeat(90)}
254998
+ ` + lines.join("\n") + (networks.some((n2) => n2.active) ? "\n\n * = currently connected" : ""),
254999
+ durationMs: performance.now() - start2
255000
+ };
255001
+ } catch (err) {
255002
+ try {
255003
+ const iwScan = execSync30(`iw dev ${iface} scan 2>/dev/null | grep -E "SSID:|signal:|freq:" | head -60`, { encoding: "utf8", timeout: 15e3 });
255004
+ return { success: true, output: `WiFi scan (iw fallback) on ${iface}:
255005
+ ${iwScan}`, durationMs: performance.now() - start2 };
255006
+ } catch {
255007
+ return { success: false, output: "", error: `WiFi scan failed on ${iface}: ${err instanceof Error ? err.message : String(err)}`, durationMs: performance.now() - start2 };
255008
+ }
255009
+ }
255010
+ }
255011
+ // =========================================================================
255012
+ // List WiFi interfaces
255013
+ // =========================================================================
255014
+ listInterfaces(start2) {
255015
+ const interfaces = [];
255016
+ try {
255017
+ const ifaces = execSync30("ls /sys/class/net/", { encoding: "utf8", timeout: 5e3 }).trim().split("\n");
255018
+ for (const iface of ifaces) {
255019
+ try {
255020
+ execSync30(`test -d /sys/class/net/${iface}/wireless`, { timeout: 2e3, stdio: "pipe" });
255021
+ let info = ` ${iface}:`;
255022
+ try {
255023
+ const driver = execSync30(`readlink /sys/class/net/${iface}/device/driver 2>/dev/null`, { encoding: "utf8", timeout: 2e3 }).trim().split("/").pop();
255024
+ info += ` driver=${driver}`;
255025
+ } catch {
255026
+ }
255027
+ try {
255028
+ const mac = execSync30(`cat /sys/class/net/${iface}/address 2>/dev/null`, { encoding: "utf8", timeout: 2e3 }).trim();
255029
+ info += ` mac=${mac}`;
255030
+ } catch {
255031
+ }
255032
+ try {
255033
+ const state = execSync30(`cat /sys/class/net/${iface}/operstate 2>/dev/null`, { encoding: "utf8", timeout: 2e3 }).trim();
255034
+ info += ` state=${state}`;
255035
+ } catch {
255036
+ }
255037
+ try {
255038
+ const uevent = execSync30(`cat /sys/class/net/${iface}/device/uevent 2>/dev/null`, { encoding: "utf8", timeout: 2e3 });
255039
+ const prodMatch = uevent.match(/PRODUCT=([^\n]+)/);
255040
+ if (prodMatch)
255041
+ info += ` usb=${prodMatch[1]}`;
255042
+ } catch {
255043
+ }
255044
+ try {
255045
+ const conn = execSync30(`nmcli -t -f NAME connection show --active 2>/dev/null | head -1`, { encoding: "utf8", timeout: 3e3 }).trim();
255046
+ const devConn = execSync30(`nmcli -t -f DEVICE connection show --active 2>/dev/null | head -1`, { encoding: "utf8", timeout: 3e3 }).trim();
255047
+ if (devConn === iface && conn)
255048
+ info += ` connected="${conn}"`;
255049
+ } catch {
255050
+ }
255051
+ interfaces.push(info);
255052
+ } catch {
255053
+ }
255054
+ }
255055
+ } catch {
255056
+ }
255057
+ try {
255058
+ const lsusb = execSync30("lsusb 2>/dev/null", { encoding: "utf8", timeout: 5e3 });
255059
+ const usbWifi = lsusb.split("\n").filter((l2) => /wireless|wifi|802\.11|rtl88|mt76|ath9k|ac600|archer/i.test(l2) && !l2.includes("Bluetooth"));
255060
+ for (const dev of usbWifi) {
255061
+ const already = interfaces.some((i2) => {
255062
+ const match = dev.match(/ID\s+([0-9a-f:]+)/i);
255063
+ return match && i2.includes(match[1].replace(":", "/"));
255064
+ });
255065
+ if (!already) {
255066
+ interfaces.push(` [no-interface] ${dev.trim()} (driver may not be loaded)`);
255067
+ }
255068
+ }
255069
+ } catch {
255070
+ }
255071
+ if (interfaces.length === 0) {
255072
+ return { success: true, output: "No WiFi interfaces found. Connect a WiFi adapter.", durationMs: performance.now() - start2 };
255073
+ }
255074
+ return {
255075
+ success: true,
255076
+ output: `WiFi interfaces:
255077
+ ${interfaces.join("\n")}`,
255078
+ durationMs: performance.now() - start2
255079
+ };
255080
+ }
255081
+ // =========================================================================
255082
+ // Connect to a network
255083
+ // =========================================================================
255084
+ connectNetwork(args, start2) {
255085
+ const ssid = args["ssid"];
255086
+ if (!ssid) {
255087
+ return { success: false, output: "", error: "Missing 'ssid'. Specify the WiFi network name to connect to.", durationMs: performance.now() - start2 };
255088
+ }
255089
+ const password = args["password"];
255090
+ const iface = args["interface"] || this.findWifiInterface();
255091
+ if (!iface) {
255092
+ return { success: false, output: "", error: "No WiFi interface available.", durationMs: performance.now() - start2 };
255093
+ }
255094
+ const cmd = password ? `nmcli device wifi connect "${ssid}" password "${password}" ifname ${iface}` : `nmcli device wifi connect "${ssid}" ifname ${iface}`;
255095
+ try {
255096
+ execSync30(cmd, { encoding: "utf8", timeout: 3e4, stdio: "pipe" });
255097
+ } catch (err) {
255098
+ const msg = err instanceof Error ? err.message : String(err);
255099
+ if (msg.includes("No network with SSID")) {
255100
+ return { success: false, output: "", error: `Network "${ssid}" not found. Run wifi_control action='scan' to see available networks.`, durationMs: performance.now() - start2 };
255101
+ }
255102
+ if (msg.includes("Secrets were required")) {
255103
+ return { success: false, output: "", error: `Password required for "${ssid}". Provide the password parameter.`, durationMs: performance.now() - start2 };
255104
+ }
255105
+ return { success: false, output: "", error: `Failed to connect to "${ssid}": ${msg.slice(0, 300)}`, durationMs: performance.now() - start2 };
255106
+ }
255107
+ try {
255108
+ execSync30("sleep 2", { timeout: 5e3 });
255109
+ const ip = execSync30(`ip addr show ${iface} | grep "inet " | awk '{print $2}'`, { encoding: "utf8", timeout: 5e3 }).trim();
255110
+ return { success: true, output: `Connected to "${ssid}" on ${iface}.
255111
+ IP address: ${ip}`, durationMs: performance.now() - start2 };
255112
+ } catch {
255113
+ return { success: true, output: `Connected to "${ssid}" on ${iface}. (IP assignment pending)`, durationMs: performance.now() - start2 };
255114
+ }
255115
+ }
255116
+ // =========================================================================
255117
+ // Disconnect
255118
+ // =========================================================================
255119
+ disconnectNetwork(args, start2) {
255120
+ const iface = args["interface"] || this.findWifiInterface();
255121
+ if (!iface) {
255122
+ return { success: false, output: "", error: "No WiFi interface found.", durationMs: performance.now() - start2 };
255123
+ }
255124
+ try {
255125
+ execSync30(`nmcli device disconnect ${iface}`, { timeout: 1e4, stdio: "pipe" });
255126
+ return { success: true, output: `Disconnected ${iface} from WiFi.`, durationMs: performance.now() - start2 };
255127
+ } catch (err) {
255128
+ return { success: false, output: "", error: `Disconnect failed: ${err instanceof Error ? err.message : String(err)}`, durationMs: performance.now() - start2 };
255129
+ }
255130
+ }
255131
+ // =========================================================================
255132
+ // Connection status
255133
+ // =========================================================================
255134
+ connectionStatus(args, start2) {
255135
+ const iface = args["interface"] || this.findWifiInterface();
255136
+ if (!iface) {
255137
+ return { success: false, output: "", error: "No WiFi interface found.", durationMs: performance.now() - start2 };
255138
+ }
255139
+ const info = [`WiFi status for ${iface}:`];
255140
+ try {
255141
+ const state = execSync30(`nmcli -t -f GENERAL.STATE device show ${iface} 2>/dev/null`, { encoding: "utf8", timeout: 5e3 });
255142
+ const stateMatch = state.match(/GENERAL\.STATE:(.+)/);
255143
+ info.push(` State: ${stateMatch ? stateMatch[1].trim() : "unknown"}`);
255144
+ } catch {
255145
+ }
255146
+ try {
255147
+ const conn = execSync30(`nmcli -t -f GENERAL.CONNECTION device show ${iface} 2>/dev/null`, { encoding: "utf8", timeout: 5e3 });
255148
+ const connMatch = conn.match(/GENERAL\.CONNECTION:(.+)/);
255149
+ info.push(` Network: ${connMatch ? connMatch[1].trim() || "(not connected)" : "(not connected)"}`);
255150
+ } catch {
255151
+ }
255152
+ try {
255153
+ const ip = execSync30(`ip addr show ${iface} 2>/dev/null | grep "inet " | awk '{print $2}'`, { encoding: "utf8", timeout: 5e3 }).trim();
255154
+ info.push(` IP: ${ip || "(no IP)"}`);
255155
+ } catch {
255156
+ }
255157
+ try {
255158
+ const iwconfig = execSync30(`iwconfig ${iface} 2>/dev/null`, { encoding: "utf8", timeout: 5e3 });
255159
+ const signalMatch = iwconfig.match(/Signal level[=:](-?\d+)\s*dBm/);
255160
+ const linkMatch = iwconfig.match(/Link Quality[=:](\d+\/\d+)/);
255161
+ const bitRateMatch = iwconfig.match(/Bit Rate[=:]([^\s]+)/);
255162
+ const freqMatch = iwconfig.match(/Frequency[=:]([^\s]+\s*GHz)/);
255163
+ if (signalMatch)
255164
+ info.push(` Signal: ${signalMatch[1]} dBm`);
255165
+ if (linkMatch)
255166
+ info.push(` Link Quality: ${linkMatch[1]}`);
255167
+ if (bitRateMatch)
255168
+ info.push(` Bit Rate: ${bitRateMatch[1]}`);
255169
+ if (freqMatch)
255170
+ info.push(` Frequency: ${freqMatch[1]}`);
255171
+ } catch {
255172
+ }
255173
+ try {
255174
+ const gw = execSync30(`ip route show dev ${iface} 2>/dev/null | grep default | awk '{print $3}'`, { encoding: "utf8", timeout: 5e3 }).trim();
255175
+ if (gw)
255176
+ info.push(` Gateway: ${gw}`);
255177
+ } catch {
255178
+ }
255179
+ try {
255180
+ const dns2 = execSync30(`nmcli -t -f IP4.DNS device show ${iface} 2>/dev/null`, { encoding: "utf8", timeout: 5e3 });
255181
+ const dnsServers = dns2.match(/IP4\.DNS\[?\d*\]?:(.+)/g);
255182
+ if (dnsServers)
255183
+ info.push(` DNS: ${dnsServers.map((d2) => d2.split(":")[1]).join(", ")}`);
255184
+ } catch {
255185
+ }
255186
+ return { success: true, output: info.join("\n"), durationMs: performance.now() - start2 };
255187
+ }
255188
+ // =========================================================================
255189
+ // Monitor mode
255190
+ // =========================================================================
255191
+ monitorMode(args, start2) {
255192
+ const iface = args["interface"] || this.findWifiInterface();
255193
+ if (!iface) {
255194
+ return { success: false, output: "", error: "No WiFi interface found.", durationMs: performance.now() - start2 };
255195
+ }
255196
+ const enable = args["enable"] !== false;
255197
+ if (enable) {
255198
+ try {
255199
+ execSync30(`ip link set ${iface} down && iw dev ${iface} set type monitor && ip link set ${iface} up`, { timeout: 1e4, stdio: "pipe" });
255200
+ return { success: true, output: `Monitor mode ENABLED on ${iface}. Use 'monitor enable=false' to restore managed mode.`, durationMs: performance.now() - start2 };
255201
+ } catch (err) {
255202
+ const msg = err instanceof Error ? err.message : String(err);
255203
+ if (msg.includes("Operation not permitted")) {
255204
+ return { success: false, output: "", error: `Monitor mode requires root. Run with sudo or use shell: sudo ip link set ${iface} down && sudo iw dev ${iface} set type monitor && sudo ip link set ${iface} up`, durationMs: performance.now() - start2 };
255205
+ }
255206
+ return { success: false, output: "", error: `Failed to enable monitor mode: ${msg.slice(0, 300)}`, durationMs: performance.now() - start2 };
255207
+ }
255208
+ } else {
255209
+ try {
255210
+ execSync30(`ip link set ${iface} down && iw dev ${iface} set type managed && ip link set ${iface} up`, { timeout: 1e4, stdio: "pipe" });
255211
+ return { success: true, output: `Monitor mode DISABLED on ${iface}. Restored to managed mode.`, durationMs: performance.now() - start2 };
255212
+ } catch (err) {
255213
+ return { success: false, output: "", error: `Failed to disable monitor mode: ${err instanceof Error ? err.message : String(err)}`, durationMs: performance.now() - start2 };
255214
+ }
255215
+ }
255216
+ }
255217
+ // =========================================================================
255218
+ // Helpers
255219
+ // =========================================================================
255220
+ findWifiInterface() {
255221
+ try {
255222
+ const ifaces = execSync30("ls /sys/class/net/", { encoding: "utf8", timeout: 3e3 }).trim().split("\n");
255223
+ for (const iface of ifaces) {
255224
+ try {
255225
+ execSync30(`test -d /sys/class/net/${iface}/wireless`, { timeout: 2e3, stdio: "pipe" });
255226
+ return iface;
255227
+ } catch {
255228
+ }
255229
+ }
255230
+ } catch {
255231
+ }
255232
+ return null;
255233
+ }
255234
+ };
255235
+ }
255236
+ });
255237
+
255238
+ // packages/execution/dist/tools/bluetooth-scan.js
255239
+ import { execSync as execSync31 } from "node:child_process";
255240
+ var BluetoothScanTool;
255241
+ var init_bluetooth_scan = __esm({
255242
+ "packages/execution/dist/tools/bluetooth-scan.js"() {
255243
+ "use strict";
255244
+ BluetoothScanTool = class {
255245
+ name = "bluetooth_scan";
255246
+ description = "Discover nearby Bluetooth devices. Actions: 'scan' to find Classic and BLE devices, 'interfaces' to list Bluetooth adapters, 'info' to get device details. Use this to discover Bluetooth peripherals, check for nearby devices, or identify what Bluetooth hardware is connected to this system.";
255247
+ parameters = {
255248
+ type: "object",
255249
+ properties: {
255250
+ action: {
255251
+ type: "string",
255252
+ enum: ["scan", "interfaces", "info"],
255253
+ description: "Action: scan for devices, list adapters, or get device info"
255254
+ },
255255
+ device: {
255256
+ type: "string",
255257
+ description: "HCI device (e.g. hci0). Default: first available."
255258
+ },
255259
+ address: {
255260
+ type: "string",
255261
+ description: "Bluetooth MAC address for 'info' action"
255262
+ },
255263
+ timeout: {
255264
+ type: "number",
255265
+ description: "Scan timeout in seconds (default: 8)"
255266
+ }
255267
+ },
255268
+ required: ["action"]
255269
+ };
255270
+ async execute(args) {
255271
+ const action = args["action"];
255272
+ const start2 = performance.now();
255273
+ try {
255274
+ switch (action) {
255275
+ case "scan":
255276
+ return this.scanDevices(args, start2);
255277
+ case "interfaces":
255278
+ return this.listInterfaces(start2);
255279
+ case "info":
255280
+ return this.deviceInfo(args, start2);
255281
+ default:
255282
+ return { success: false, output: "", error: `Unknown action: ${action}`, durationMs: performance.now() - start2 };
255283
+ }
255284
+ } catch (err) {
255285
+ return { success: false, output: "", error: `bluetooth_scan error: ${err instanceof Error ? err.message : String(err)}`, durationMs: performance.now() - start2 };
255286
+ }
255287
+ }
255288
+ scanDevices(args, start2) {
255289
+ const hci = args["device"] || "hci0";
255290
+ const timeout2 = args["timeout"] || 8;
255291
+ const devices = [];
255292
+ try {
255293
+ const classic = execSync31(`hcitool -i ${hci} scan --length=${timeout2} 2>/dev/null`, { encoding: "utf8", timeout: (timeout2 + 5) * 1e3 });
255294
+ for (const line of classic.split("\n")) {
255295
+ const match = line.trim().match(/^([0-9A-F:]{17})\s+(.+)$/i);
255296
+ if (match)
255297
+ devices.push({ mac: match[1], name: match[2].trim(), type: "classic" });
255298
+ }
255299
+ } catch {
255300
+ }
255301
+ try {
255302
+ const ble = execSync31(`timeout ${Math.min(timeout2, 5)} hcitool -i ${hci} lescan --duplicates 2>/dev/null || true`, { encoding: "utf8", timeout: (timeout2 + 5) * 1e3 });
255303
+ const seen = /* @__PURE__ */ new Set();
255304
+ for (const line of ble.split("\n")) {
255305
+ const match = line.trim().match(/^([0-9A-F:]{17})\s+(.*)$/i);
255306
+ if (match && !seen.has(match[1])) {
255307
+ seen.add(match[1]);
255308
+ devices.push({ mac: match[1], name: match[2].trim() || "(unnamed)", type: "ble" });
255309
+ }
255310
+ }
255311
+ } catch {
255312
+ }
255313
+ if (devices.length === 0) {
255314
+ try {
255315
+ const btctl = execSync31(`echo -e "scan on\\n" | timeout ${timeout2} bluetoothctl 2>/dev/null | grep "Device "`, { encoding: "utf8", timeout: (timeout2 + 5) * 1e3 });
255316
+ for (const line of btctl.split("\n")) {
255317
+ const match = line.match(/Device\s+([0-9A-F:]{17})\s+(.+)/i);
255318
+ if (match)
255319
+ devices.push({ mac: match[1], name: match[2].trim(), type: "unknown" });
255320
+ }
255321
+ } catch {
255322
+ }
255323
+ }
255324
+ if (devices.length === 0) {
255325
+ return { success: true, output: `No Bluetooth devices found within ${timeout2}s scan on ${hci}.
255326
+ Tip: Make sure target devices are in discoverable/pairing mode.`, durationMs: performance.now() - start2 };
255327
+ }
255328
+ const lines = devices.map((d2) => ` ${d2.mac} ${d2.name.padEnd(30)} [${d2.type}]`);
255329
+ return {
255330
+ success: true,
255331
+ output: `Found ${devices.length} Bluetooth device(s) on ${hci}:
255332
+ ${lines.join("\n")}`,
255333
+ durationMs: performance.now() - start2
255334
+ };
255335
+ }
255336
+ listInterfaces(start2) {
255337
+ const adapters = [];
255338
+ try {
255339
+ const hciconfig = execSync31("hciconfig -a 2>/dev/null", { encoding: "utf8", timeout: 5e3 });
255340
+ const blocks = hciconfig.split(/^(hci\d+)/m);
255341
+ for (let i2 = 1; i2 < blocks.length; i2 += 2) {
255342
+ const name10 = blocks[i2];
255343
+ const info = blocks[i2 + 1] || "";
255344
+ const bdAddr = info.match(/BD Address:\s*([0-9A-F:]{17})/i)?.[1] || "unknown";
255345
+ const state = info.includes("UP RUNNING") ? "up" : info.includes("DOWN") ? "down" : "unknown";
255346
+ const type = info.match(/Type:\s*(\w+)/)?.[1] || "";
255347
+ adapters.push(` ${name10}: ${bdAddr} state=${state} ${type}`);
255348
+ }
255349
+ } catch {
255350
+ try {
255351
+ const devs = execSync31("ls /sys/class/bluetooth/ 2>/dev/null", { encoding: "utf8", timeout: 3e3 }).trim().split("\n").filter(Boolean);
255352
+ for (const dev of devs) {
255353
+ const addr = execSync31(`cat /sys/class/bluetooth/${dev}/address 2>/dev/null`, { encoding: "utf8", timeout: 2e3 }).trim();
255354
+ adapters.push(` ${dev}: ${addr}`);
255355
+ }
255356
+ } catch {
255357
+ }
255358
+ }
255359
+ if (adapters.length === 0) {
255360
+ return { success: true, output: "No Bluetooth adapters found.", durationMs: performance.now() - start2 };
255361
+ }
255362
+ return { success: true, output: `Bluetooth adapters:
255363
+ ${adapters.join("\n")}`, durationMs: performance.now() - start2 };
255364
+ }
255365
+ deviceInfo(args, start2) {
255366
+ const address = args["address"];
255367
+ if (!address) {
255368
+ return { success: false, output: "", error: "Missing 'address'. Provide a Bluetooth MAC address.", durationMs: performance.now() - start2 };
255369
+ }
255370
+ try {
255371
+ const info = execSync31(`hcitool info ${address} 2>/dev/null`, { encoding: "utf8", timeout: 1e4 });
255372
+ return { success: true, output: `Bluetooth device ${address}:
255373
+ ${info}`, durationMs: performance.now() - start2 };
255374
+ } catch {
255375
+ return { success: true, output: `Could not query ${address}. Device may be out of range or not in discoverable mode.`, durationMs: performance.now() - start2 };
255376
+ }
255377
+ }
255378
+ };
255379
+ }
255380
+ });
255381
+
254887
255382
  // packages/execution/dist/tools/full-sub-agent.js
254888
255383
  import { spawn as spawn13, ChildProcess } from "node:child_process";
254889
255384
  import { randomBytes as randomBytes13 } from "node:crypto";
@@ -255328,7 +255823,7 @@ var init_agent_tool = __esm({
255328
255823
  });
255329
255824
 
255330
255825
  // packages/execution/dist/tools/worktree.js
255331
- import { execSync as execSync30 } from "node:child_process";
255826
+ import { execSync as execSync32 } from "node:child_process";
255332
255827
  import { existsSync as existsSync31, mkdirSync as mkdirSync12, rmSync } from "node:fs";
255333
255828
  import { join as join46, resolve as resolve30 } from "node:path";
255334
255829
  function validateSlug(slug) {
@@ -255347,7 +255842,7 @@ function flattenSlug(slug) {
255347
255842
  }
255348
255843
  function isGitRepo(cwd4) {
255349
255844
  try {
255350
- execSync30("git rev-parse --is-inside-work-tree", { cwd: cwd4, stdio: "pipe" });
255845
+ execSync32("git rev-parse --is-inside-work-tree", { cwd: cwd4, stdio: "pipe" });
255351
255846
  return true;
255352
255847
  } catch {
255353
255848
  return false;
@@ -255355,14 +255850,14 @@ function isGitRepo(cwd4) {
255355
255850
  }
255356
255851
  function getCurrentBranch(cwd4) {
255357
255852
  try {
255358
- return execSync30("git rev-parse --abbrev-ref HEAD", { cwd: cwd4, stdio: "pipe" }).toString().trim();
255853
+ return execSync32("git rev-parse --abbrev-ref HEAD", { cwd: cwd4, stdio: "pipe" }).toString().trim();
255359
255854
  } catch {
255360
255855
  return void 0;
255361
255856
  }
255362
255857
  }
255363
255858
  function getCurrentCommit(cwd4) {
255364
255859
  try {
255365
- return execSync30("git rev-parse --short HEAD", { cwd: cwd4, stdio: "pipe" }).toString().trim();
255860
+ return execSync32("git rev-parse --short HEAD", { cwd: cwd4, stdio: "pipe" }).toString().trim();
255366
255861
  } catch {
255367
255862
  return void 0;
255368
255863
  }
@@ -255393,13 +255888,13 @@ function createWorktree(repoRoot, slug) {
255393
255888
  }
255394
255889
  mkdirSync12(worktreeBase, { recursive: true });
255395
255890
  try {
255396
- execSync30(`git worktree add "${worktreePath}" -b "${branchName}"`, {
255891
+ execSync32(`git worktree add "${worktreePath}" -b "${branchName}"`, {
255397
255892
  cwd: repoRoot,
255398
255893
  stdio: "pipe"
255399
255894
  });
255400
255895
  } catch (err) {
255401
255896
  try {
255402
- execSync30(`git worktree add "${worktreePath}" "${branchName}"`, {
255897
+ execSync32(`git worktree add "${worktreePath}" "${branchName}"`, {
255403
255898
  cwd: repoRoot,
255404
255899
  stdio: "pipe"
255405
255900
  });
@@ -255421,7 +255916,7 @@ function createWorktree(repoRoot, slug) {
255421
255916
  }
255422
255917
  function worktreeHasChanges(worktreePath) {
255423
255918
  try {
255424
- const status = execSync30("git status --porcelain", {
255919
+ const status = execSync32("git status --porcelain", {
255425
255920
  cwd: worktreePath,
255426
255921
  stdio: "pipe"
255427
255922
  }).toString().trim();
@@ -255442,20 +255937,20 @@ function removeWorktree(repoRoot, slug, force = false) {
255442
255937
  return "Worktree has uncommitted changes. Use force=true to discard, or commit/stash first.";
255443
255938
  }
255444
255939
  try {
255445
- execSync30(`git worktree remove "${worktreePath}" ${force ? "--force" : ""}`, {
255940
+ execSync32(`git worktree remove "${worktreePath}" ${force ? "--force" : ""}`, {
255446
255941
  cwd: repoRoot,
255447
255942
  stdio: "pipe"
255448
255943
  });
255449
255944
  } catch (err) {
255450
255945
  try {
255451
255946
  rmSync(worktreePath, { recursive: true, force: true });
255452
- execSync30("git worktree prune", { cwd: repoRoot, stdio: "pipe" });
255947
+ execSync32("git worktree prune", { cwd: repoRoot, stdio: "pipe" });
255453
255948
  } catch {
255454
255949
  return `Failed to remove worktree: ${err}`;
255455
255950
  }
255456
255951
  }
255457
255952
  try {
255458
- execSync30(`git branch -D "${branchName}"`, { cwd: repoRoot, stdio: "pipe" });
255953
+ execSync32(`git branch -D "${branchName}"`, { cwd: repoRoot, stdio: "pipe" });
255459
255954
  } catch {
255460
255955
  }
255461
255956
  _sessions.delete(slug);
@@ -256732,7 +257227,7 @@ var init_notebook_edit = __esm({
256732
257227
  });
256733
257228
 
256734
257229
  // packages/execution/dist/tools/environment-snapshot.js
256735
- import { execSync as execSync31 } from "node:child_process";
257230
+ import { execSync as execSync33 } from "node:child_process";
256736
257231
  import { cpus, totalmem, freemem, hostname as hostname2, platform, arch, uptime } from "node:os";
256737
257232
  import { statfsSync } from "node:fs";
256738
257233
  function collectSnapshot(workingDir) {
@@ -256750,7 +257245,7 @@ function collectSnapshot(workingDir) {
256750
257245
  }
256751
257246
  let gpu = void 0;
256752
257247
  try {
256753
- const nvOut = execSync31("nvidia-smi --query-gpu=name,memory.total,memory.used,temperature.gpu --format=csv,noheader,nounits", { encoding: "utf-8", timeout: 3e3, stdio: ["pipe", "pipe", "pipe"] }).trim().split(",").map((s2) => s2.trim());
257248
+ const nvOut = execSync33("nvidia-smi --query-gpu=name,memory.total,memory.used,temperature.gpu --format=csv,noheader,nounits", { encoding: "utf-8", timeout: 3e3, stdio: ["pipe", "pipe", "pipe"] }).trim().split(",").map((s2) => s2.trim());
256754
257249
  if (nvOut.length >= 3) {
256755
257250
  gpu = {
256756
257251
  name: nvOut[0],
@@ -256765,12 +257260,12 @@ function collectSnapshot(workingDir) {
256765
257260
  let battery = void 0;
256766
257261
  try {
256767
257262
  if (platform() === "linux") {
256768
- const cap = execSync31("cat /sys/class/power_supply/BAT0/capacity 2>/dev/null", { encoding: "utf-8", timeout: 1e3 }).trim();
256769
- const status = execSync31("cat /sys/class/power_supply/BAT0/status 2>/dev/null", { encoding: "utf-8", timeout: 1e3 }).trim();
257263
+ const cap = execSync33("cat /sys/class/power_supply/BAT0/capacity 2>/dev/null", { encoding: "utf-8", timeout: 1e3 }).trim();
257264
+ const status = execSync33("cat /sys/class/power_supply/BAT0/status 2>/dev/null", { encoding: "utf-8", timeout: 1e3 }).trim();
256770
257265
  if (cap)
256771
257266
  battery = { percent: parseInt(cap, 10), charging: status === "Charging" || status === "Full" };
256772
257267
  } else if (platform() === "darwin") {
256773
- const pmOut = execSync31("pmset -g batt", { encoding: "utf-8", timeout: 2e3 });
257268
+ const pmOut = execSync33("pmset -g batt", { encoding: "utf-8", timeout: 2e3 });
256774
257269
  const match = pmOut.match(/(\d+)%;\s*(charging|discharging|charged)/i);
256775
257270
  if (match)
256776
257271
  battery = { percent: parseInt(match[1], 10), charging: match[2].toLowerCase() !== "discharging" };
@@ -256791,8 +257286,8 @@ function collectSnapshot(workingDir) {
256791
257286
  }
256792
257287
  let processInfo = { total: 0, nodeCount: 0, oaSpawned: 0, topCpu: [] };
256793
257288
  try {
256794
- const psLines = execSync31("ps -eo pid,%cpu,args --sort=-%cpu --no-headers 2>/dev/null | head -50", { encoding: "utf-8", timeout: 3e3, stdio: ["pipe", "pipe", "pipe"] }).trim().split("\n");
256795
- const total = parseInt(execSync31("ps aux | wc -l", { encoding: "utf-8", timeout: 2e3 }).trim(), 10);
257289
+ const psLines = execSync33("ps -eo pid,%cpu,args --sort=-%cpu --no-headers 2>/dev/null | head -50", { encoding: "utf-8", timeout: 3e3, stdio: ["pipe", "pipe", "pipe"] }).trim().split("\n");
257290
+ const total = parseInt(execSync33("ps aux | wc -l", { encoding: "utf-8", timeout: 2e3 }).trim(), 10);
256796
257291
  let nodeCount = 0;
256797
257292
  let oaSpawned = 0;
256798
257293
  const topCpu = [];
@@ -256873,7 +257368,7 @@ var init_environment_snapshot = __esm({
256873
257368
  });
256874
257369
 
256875
257370
  // packages/execution/dist/tools/video-understand.js
256876
- import { execSync as execSync32 } from "node:child_process";
257371
+ import { execSync as execSync34 } from "node:child_process";
256877
257372
  import { existsSync as existsSync35, mkdirSync as mkdirSync13, writeFileSync as writeFileSync13, readFileSync as readFileSync26, readdirSync as readdirSync8, unlinkSync as unlinkSync7 } from "node:fs";
256878
257373
  import { join as join49, basename as basename11 } from "node:path";
256879
257374
  import { createHash as createHash2 } from "node:crypto";
@@ -256882,11 +257377,11 @@ function isYouTubeUrl2(url) {
256882
257377
  }
256883
257378
  function ensureYtDlp2() {
256884
257379
  try {
256885
- execSync32("yt-dlp --version", { timeout: 5e3, stdio: "pipe" });
257380
+ execSync34("yt-dlp --version", { timeout: 5e3, stdio: "pipe" });
256886
257381
  return true;
256887
257382
  } catch {
256888
257383
  try {
256889
- execSync32("pip3 install --break-system-packages yt-dlp 2>/dev/null || pip3 install --user yt-dlp 2>/dev/null", { timeout: 6e4, stdio: "pipe" });
257384
+ execSync34("pip3 install --break-system-packages yt-dlp 2>/dev/null || pip3 install --user yt-dlp 2>/dev/null", { timeout: 6e4, stdio: "pipe" });
256890
257385
  return true;
256891
257386
  } catch {
256892
257387
  return false;
@@ -256895,7 +257390,7 @@ function ensureYtDlp2() {
256895
257390
  }
256896
257391
  function ensureFfmpeg() {
256897
257392
  try {
256898
- execSync32("ffmpeg -version", { timeout: 3e3, stdio: "pipe" });
257393
+ execSync34("ffmpeg -version", { timeout: 3e3, stdio: "pipe" });
256899
257394
  return true;
256900
257395
  } catch {
256901
257396
  return false;
@@ -256975,32 +257470,32 @@ var init_video_understand = __esm({
256975
257470
  return { success: false, output: "", error: "yt-dlp required but not available. Install: pip3 install yt-dlp", durationMs: performance.now() - start2 };
256976
257471
  }
256977
257472
  try {
256978
- execSync32(`yt-dlp -f "worst[ext=mp4]" -o "${join49(tmpDir, "video.%(ext)s")}" "${url}"`, { timeout: 3e5, stdio: "pipe" });
257473
+ execSync34(`yt-dlp -f "worst[ext=mp4]" -o "${join49(tmpDir, "video.%(ext)s")}" "${url}"`, { timeout: 3e5, stdio: "pipe" });
256979
257474
  } catch {
256980
- execSync32(`yt-dlp -f worst -o "${join49(tmpDir, "video.%(ext)s")}" "${url}"`, { timeout: 3e5, stdio: "pipe" });
257475
+ execSync34(`yt-dlp -f worst -o "${join49(tmpDir, "video.%(ext)s")}" "${url}"`, { timeout: 3e5, stdio: "pipe" });
256981
257476
  }
256982
- execSync32(`yt-dlp -x --audio-format mp3 --audio-quality 5 -o "${join49(tmpDir, "audio.%(ext)s")}" "${url}"`, { timeout: 3e5, stdio: "pipe" });
257477
+ execSync34(`yt-dlp -x --audio-format mp3 --audio-quality 5 -o "${join49(tmpDir, "audio.%(ext)s")}" "${url}"`, { timeout: 3e5, stdio: "pipe" });
256983
257478
  try {
256984
- title = execSync32(`yt-dlp --get-title "${url}"`, { encoding: "utf-8", timeout: 15e3, stdio: ["pipe", "pipe", "pipe"] }).trim();
257479
+ title = execSync34(`yt-dlp --get-title "${url}"`, { encoding: "utf-8", timeout: 15e3, stdio: ["pipe", "pipe", "pipe"] }).trim();
256985
257480
  } catch {
256986
257481
  }
256987
257482
  } else {
256988
- execSync32(`curl -sL -o "${join49(tmpDir, "video.mp4")}" "${url}"`, { timeout: 3e5, stdio: "pipe" });
256989
- execSync32(`ffmpeg -i "${join49(tmpDir, "video.mp4")}" -vn -acodec libmp3lame -q:a 5 "${join49(tmpDir, "audio.mp3")}" -y`, { timeout: 12e4, stdio: "pipe" });
257483
+ execSync34(`curl -sL -o "${join49(tmpDir, "video.mp4")}" "${url}"`, { timeout: 3e5, stdio: "pipe" });
257484
+ execSync34(`ffmpeg -i "${join49(tmpDir, "video.mp4")}" -vn -acodec libmp3lame -q:a 5 "${join49(tmpDir, "audio.mp3")}" -y`, { timeout: 12e4, stdio: "pipe" });
256990
257485
  }
256991
257486
  videoPath = readdirSync8(tmpDir).find((f2) => f2.startsWith("video")) ? join49(tmpDir, readdirSync8(tmpDir).find((f2) => f2.startsWith("video"))) : join49(tmpDir, "video.mp4");
256992
257487
  audioPath = readdirSync8(tmpDir).find((f2) => f2.startsWith("audio")) ? join49(tmpDir, readdirSync8(tmpDir).find((f2) => f2.startsWith("audio"))) : join49(tmpDir, "audio.mp3");
256993
257488
  } else {
256994
257489
  videoPath = localPath;
256995
257490
  audioPath = join49(tmpDir, "audio.mp3");
256996
- execSync32(`ffmpeg -i "${videoPath}" -vn -acodec libmp3lame -q:a 5 "${audioPath}" -y`, { timeout: 12e4, stdio: "pipe" });
257491
+ execSync34(`ffmpeg -i "${videoPath}" -vn -acodec libmp3lame -q:a 5 "${audioPath}" -y`, { timeout: 12e4, stdio: "pipe" });
256997
257492
  }
256998
257493
  let segments = [];
256999
257494
  let language = "en";
257000
257495
  let duration = 0;
257001
257496
  try {
257002
257497
  const jsonOut = join49(tmpDir, "transcript.json");
257003
- execSync32(`transcribe-cli transcribe "${audioPath}" --model ${whisperModel} --format json -o "${tmpDir}"`, { timeout: 6e5, stdio: "pipe" });
257498
+ execSync34(`transcribe-cli transcribe "${audioPath}" --model ${whisperModel} --format json -o "${tmpDir}"`, { timeout: 6e5, stdio: "pipe" });
257004
257499
  const jsonFile = readdirSync8(tmpDir).find((f2) => f2.endsWith(".json") && f2 !== "result.json");
257005
257500
  if (jsonFile) {
257006
257501
  const data = JSON.parse(readFileSync26(join49(tmpDir, jsonFile), "utf-8"));
@@ -257023,7 +257518,7 @@ var init_video_understand = __esm({
257023
257518
  const fps = 25;
257024
257519
  const intervalFrames = Math.max(1, frameInterval * fps);
257025
257520
  try {
257026
- execSync32(`ffmpeg -i "${videoPath}" -vf "select='gt(scene\\,${sceneThreshold})+not(mod(n\\,${intervalFrames}))',showinfo" -vsync vfr "${join49(framesDir, "frame_%04d.jpg")}" -y`, { timeout: 3e5, stdio: "pipe" });
257521
+ execSync34(`ffmpeg -i "${videoPath}" -vf "select='gt(scene\\,${sceneThreshold})+not(mod(n\\,${intervalFrames}))',showinfo" -vsync vfr "${join49(framesDir, "frame_%04d.jpg")}" -y`, { timeout: 3e5, stdio: "pipe" });
257027
257522
  } catch {
257028
257523
  }
257029
257524
  const frameFiles = readdirSync8(framesDir).filter((f2) => f2.endsWith(".jpg")).sort();
@@ -257156,7 +257651,7 @@ Topic: ${segments.slice(0, 5).map((s2) => s2.text).join(" ").slice(0, 300)}`,
257156
257651
  }
257157
257652
  }
257158
257653
  try {
257159
- execSync32(`rm -rf "${tmpDir}"`, { timeout: 1e4, stdio: "pipe" });
257654
+ execSync34(`rm -rf "${tmpDir}"`, { timeout: 1e4, stdio: "pipe" });
257160
257655
  } catch {
257161
257656
  }
257162
257657
  return {
@@ -258050,6 +258545,7 @@ __export(dist_exports, {
258050
258545
  BackgroundRunTool: () => BackgroundRunTool,
258051
258546
  BackgroundTaskManager: () => BackgroundTaskManager,
258052
258547
  BatchEditTool: () => BatchEditTool,
258548
+ BluetoothScanTool: () => BluetoothScanTool,
258053
258549
  BrowserActionTool: () => BrowserActionTool,
258054
258550
  CameraCaptureTool: () => CameraCaptureTool,
258055
258551
  CodeSandboxTool: () => CodeSandboxTool,
@@ -258125,6 +258621,7 @@ __export(dist_exports, {
258125
258621
  WebCrawlTool: () => WebCrawlTool,
258126
258622
  WebFetchTool: () => WebFetchTool,
258127
258623
  WebSearchTool: () => WebSearchTool,
258624
+ WifiControlTool: () => WifiControlTool,
258128
258625
  WorkingNotesTool: () => WorkingNotesTool,
258129
258626
  YouTubeDownloadTool: () => YouTubeDownloadTool,
258130
258627
  addProjectConstraint: () => addProjectConstraint,
@@ -258286,6 +258783,8 @@ var init_dist4 = __esm({
258286
258783
  init_camera_capture();
258287
258784
  init_audio_capture();
258288
258785
  init_audio_playback();
258786
+ init_wifi_control();
258787
+ init_bluetooth_scan();
258289
258788
  init_system_auth();
258290
258789
  init_full_sub_agent();
258291
258790
  init_agent_tool();
@@ -261190,12 +261689,12 @@ var init_tool_batching = __esm({
261190
261689
  });
261191
261690
 
261192
261691
  // packages/orchestrator/dist/hooks.js
261193
- import { execSync as execSync33 } from "node:child_process";
261692
+ import { execSync as execSync35 } from "node:child_process";
261194
261693
  function executeHook(hook, env2 = {}) {
261195
261694
  const start2 = performance.now();
261196
261695
  const timeout2 = hook.timeoutMs ?? DEFAULT_HOOK_TIMEOUT;
261197
261696
  try {
261198
- const output = execSync33(hook.command, {
261697
+ const output = execSync35(hook.command, {
261199
261698
  timeout: timeout2,
261200
261699
  env: { ...process.env, ...env2 },
261201
261700
  encoding: "utf8",
@@ -265419,7 +265918,7 @@ ${result}`
265419
265918
  const buffer2 = Buffer.from(rawBase64, "base64");
265420
265919
  let resizedBase64 = null;
265421
265920
  try {
265422
- const { execSync: execSync46 } = await import("node:child_process");
265921
+ const { execSync: execSync48 } = await import("node:child_process");
265423
265922
  const { writeFileSync: writeFileSync38, readFileSync: readFileSync56, unlinkSync: unlinkSync17 } = await import("node:fs");
265424
265923
  const { join: join91 } = await import("node:path");
265425
265924
  const { tmpdir: tmpdir14 } = await import("node:os");
@@ -265429,7 +265928,7 @@ ${result}`
265429
265928
  const pyBin = process.platform === "win32" ? "python" : "python3";
265430
265929
  const escapedIn = tmpIn.replace(/\\/g, "\\\\");
265431
265930
  const escapedOut = tmpOut.replace(/\\/g, "\\\\");
265432
- execSync46(`${pyBin} -c "from PIL import Image; img = Image.open('${escapedIn}'); img.thumbnail((512, 512), Image.LANCZOS); img = img.convert('RGB'); img.save('${escapedOut}', 'JPEG', quality=75)"`, { timeout: 1e4, stdio: "pipe" });
265931
+ execSync48(`${pyBin} -c "from PIL import Image; img = Image.open('${escapedIn}'); img.thumbnail((512, 512), Image.LANCZOS); img = img.convert('RGB'); img.save('${escapedOut}', 'JPEG', quality=75)"`, { timeout: 1e4, stdio: "pipe" });
265433
265932
  const resizedBuf = readFileSync56(tmpOut);
265434
265933
  resizedBase64 = `data:image/jpeg;base64,${resizedBuf.toString("base64")}`;
265435
265934
  try {
@@ -265483,8 +265982,8 @@ ${result}`
265483
265982
  if (!res.ok && model === "moondream" && res.status === 404) {
265484
265983
  this.emit({ type: "status", content: `Pulling moondream vision model...`, timestamp: (/* @__PURE__ */ new Date()).toISOString() });
265485
265984
  try {
265486
- const { execSync: execSync46 } = await import("node:child_process");
265487
- execSync46("ollama pull moondream", { timeout: 3e5, stdio: "pipe" });
265985
+ const { execSync: execSync48 } = await import("node:child_process");
265986
+ execSync48("ollama pull moondream", { timeout: 3e5, stdio: "pipe" });
265488
265987
  res = await fetch(`${ollamaHost}/api/generate`, {
265489
265988
  method: "POST",
265490
265989
  headers: { "Content-Type": "application/json" },
@@ -267848,7 +268347,7 @@ __export(listen_exports, {
267848
268347
  isVideoPath: () => isVideoPath,
267849
268348
  waitForTranscribeCli: () => waitForTranscribeCli
267850
268349
  });
267851
- import { spawn as spawn17, execSync as execSync34 } from "node:child_process";
268350
+ import { spawn as spawn17, execSync as execSync36 } from "node:child_process";
267852
268351
  import { existsSync as existsSync41, mkdirSync as mkdirSync16, writeFileSync as writeFileSync17, readdirSync as readdirSync9 } from "node:fs";
267853
268352
  import { join as join57, dirname as dirname16 } from "node:path";
267854
268353
  import { homedir as homedir15 } from "node:os";
@@ -267870,7 +268369,7 @@ function findMicCaptureCommand() {
267870
268369
  const platform6 = process.platform;
267871
268370
  if (platform6 === "linux") {
267872
268371
  try {
267873
- execSync34("which arecord", { stdio: "pipe" });
268372
+ execSync36("which arecord", { stdio: "pipe" });
267874
268373
  return {
267875
268374
  cmd: "arecord",
267876
268375
  args: ["-f", "S16_LE", "-r", "16000", "-c", "1", "-t", "raw", "-q", "-"]
@@ -267880,7 +268379,7 @@ function findMicCaptureCommand() {
267880
268379
  }
267881
268380
  if (platform6 === "darwin") {
267882
268381
  try {
267883
- execSync34("which sox", { stdio: "pipe" });
268382
+ execSync36("which sox", { stdio: "pipe" });
267884
268383
  return {
267885
268384
  cmd: "sox",
267886
268385
  args: ["-d", "-t", "raw", "-r", "16000", "-c", "1", "-b", "16", "-e", "signed-integer", "-"]
@@ -267889,7 +268388,7 @@ function findMicCaptureCommand() {
267889
268388
  }
267890
268389
  }
267891
268390
  try {
267892
- execSync34("which ffmpeg", { stdio: "pipe" });
268391
+ execSync36("which ffmpeg", { stdio: "pipe" });
267893
268392
  if (platform6 === "linux") {
267894
268393
  return {
267895
268394
  cmd: "ffmpeg",
@@ -267947,7 +268446,7 @@ function findLiveWhisperScript() {
267947
268446
  if (existsSync41(p2)) return p2;
267948
268447
  }
267949
268448
  try {
267950
- const globalRoot = execSync34("npm root -g", {
268449
+ const globalRoot = execSync36("npm root -g", {
267951
268450
  encoding: "utf-8",
267952
268451
  timeout: 5e3,
267953
268452
  stdio: ["pipe", "pipe", "pipe"]
@@ -267977,7 +268476,7 @@ function ensureTranscribeCliBackground() {
267977
268476
  if (_bgInstallPromise) return;
267978
268477
  _bgInstallPromise = (async () => {
267979
268478
  try {
267980
- const globalRoot = execSync34("npm root -g", {
268479
+ const globalRoot = execSync36("npm root -g", {
267981
268480
  encoding: "utf-8",
267982
268481
  timeout: 5e3,
267983
268482
  stdio: ["pipe", "pipe", "pipe"]
@@ -268179,7 +268678,7 @@ var init_listen = __esm({
268179
268678
  }
268180
268679
  if (!this.transcribeCliAvailable) {
268181
268680
  try {
268182
- execSync34("which transcribe-cli", { stdio: "pipe" });
268681
+ execSync36("which transcribe-cli", { stdio: "pipe" });
268183
268682
  this.transcribeCliAvailable = true;
268184
268683
  } catch {
268185
268684
  this.transcribeCliAvailable = false;
@@ -268196,7 +268695,7 @@ var init_listen = __esm({
268196
268695
  } catch {
268197
268696
  }
268198
268697
  try {
268199
- const globalRoot = execSync34("npm root -g", {
268698
+ const globalRoot = execSync36("npm root -g", {
268200
268699
  encoding: "utf-8",
268201
268700
  timeout: 5e3,
268202
268701
  stdio: ["pipe", "pipe", "pipe"]
@@ -268245,7 +268744,7 @@ var init_listen = __esm({
268245
268744
  }
268246
268745
  if (!tc) {
268247
268746
  try {
268248
- execSync34("npm i -g transcribe-cli", { stdio: "pipe", timeout: 18e4 });
268747
+ execSync36("npm i -g transcribe-cli", { stdio: "pipe", timeout: 18e4 });
268249
268748
  this.transcribeCliAvailable = null;
268250
268749
  tc = await this.loadTranscribeCli();
268251
268750
  } catch {
@@ -268423,7 +268922,7 @@ transcribe-cli error: ${transcribeCliError}` : "";
268423
268922
  }
268424
268923
  if (!tc) {
268425
268924
  try {
268426
- execSync34("npm i -g transcribe-cli", { stdio: "pipe", timeout: 18e4 });
268925
+ execSync36("npm i -g transcribe-cli", { stdio: "pipe", timeout: 18e4 });
268427
268926
  this.transcribeCliAvailable = null;
268428
268927
  tc = await this.loadTranscribeCli();
268429
268928
  } catch {
@@ -268476,7 +268975,7 @@ transcribe-cli error: ${transcribeCliError}` : "";
268476
268975
  }
268477
268976
  if (!tc) {
268478
268977
  try {
268479
- execSync34("npm i -g transcribe-cli", { stdio: "pipe", timeout: 18e4 });
268978
+ execSync36("npm i -g transcribe-cli", { stdio: "pipe", timeout: 18e4 });
268480
268979
  this.transcribeCliAvailable = null;
268481
268980
  tc = await this.loadTranscribeCli();
268482
268981
  } catch {
@@ -273398,7 +273897,7 @@ var init_render = __esm({
273398
273897
 
273399
273898
  // packages/cli/src/tui/voice-session.ts
273400
273899
  import { createServer as createServer3 } from "node:http";
273401
- import { spawn as spawn18, execSync as execSync35 } from "node:child_process";
273900
+ import { spawn as spawn18, execSync as execSync37 } from "node:child_process";
273402
273901
  import { EventEmitter as EventEmitter4 } from "node:events";
273403
273902
  function generateFrontendHTML() {
273404
273903
  return `<!DOCTYPE html>
@@ -279267,7 +279766,7 @@ __export(text_selection_exports, {
279267
279766
  stripAnsi: () => stripAnsi,
279268
279767
  visibleLength: () => visibleLength
279269
279768
  });
279270
- import { execSync as execSync36 } from "node:child_process";
279769
+ import { execSync as execSync38 } from "node:child_process";
279271
279770
  function stripAnsi(s2) {
279272
279771
  return s2.replace(/\x1B\[[0-9;]*[A-Za-z]|\x1B\].*?(?:\x07|\x1B\\)/g, "");
279273
279772
  }
@@ -279278,16 +279777,16 @@ function copyText(text) {
279278
279777
  try {
279279
279778
  const platform6 = process.platform;
279280
279779
  if (platform6 === "darwin") {
279281
- execSync36("pbcopy", { input: text, timeout: 3e3 });
279780
+ execSync38("pbcopy", { input: text, timeout: 3e3 });
279282
279781
  return true;
279283
279782
  }
279284
279783
  if (platform6 === "win32") {
279285
- execSync36("clip", { input: text, timeout: 3e3 });
279784
+ execSync38("clip", { input: text, timeout: 3e3 });
279286
279785
  return true;
279287
279786
  }
279288
279787
  for (const tool of ["xclip -selection clipboard", "xsel --clipboard --input", "wl-copy"]) {
279289
279788
  try {
279290
- execSync36(tool, { input: text, timeout: 3e3 });
279789
+ execSync38(tool, { input: text, timeout: 3e3 });
279291
279790
  return true;
279292
279791
  } catch {
279293
279792
  continue;
@@ -279296,10 +279795,10 @@ function copyText(text) {
279296
279795
  if (!_clipboardAutoInstallAttempted) {
279297
279796
  _clipboardAutoInstallAttempted = true;
279298
279797
  try {
279299
- execSync36("which apt-get", { timeout: 2e3, stdio: "pipe" });
279798
+ execSync38("which apt-get", { timeout: 2e3, stdio: "pipe" });
279300
279799
  try {
279301
- execSync36("sudo -n apt-get install -y xclip 2>/dev/null", { timeout: 15e3, stdio: "pipe" });
279302
- execSync36("xclip -selection clipboard", { input: text, timeout: 3e3 });
279800
+ execSync38("sudo -n apt-get install -y xclip 2>/dev/null", { timeout: 15e3, stdio: "pipe" });
279801
+ execSync38("xclip -selection clipboard", { input: text, timeout: 3e3 });
279303
279802
  return true;
279304
279803
  } catch {
279305
279804
  }
@@ -283177,7 +283676,7 @@ __export(personaplex_exports, {
283177
283676
  import { existsSync as existsSync46, writeFileSync as writeFileSync21, readFileSync as readFileSync36, mkdirSync as mkdirSync20, copyFileSync as copyFileSync2, readdirSync as readdirSync12, statSync as statSync16 } from "node:fs";
283178
283677
  import { join as join63, dirname as dirname20 } from "node:path";
283179
283678
  import { homedir as homedir17 } from "node:os";
283180
- import { execSync as execSync37, spawn as spawn20 } from "node:child_process";
283679
+ import { execSync as execSync39, spawn as spawn20 } from "node:child_process";
283181
283680
  import { fileURLToPath as fileURLToPath12 } from "node:url";
283182
283681
  function execAsync(cmd, opts = {}) {
283183
283682
  return new Promise((resolve39, reject) => {
@@ -283210,7 +283709,7 @@ function detectJetson() {
283210
283709
  try {
283211
283710
  const model = readFileSync36("/proc/device-tree/model", "utf8").replace(/\0/g, "").trim();
283212
283711
  if (/jetson|orin|tegra/i.test(model)) {
283213
- const memInfo = execSync37("grep MemTotal /proc/meminfo", { encoding: "utf8", timeout: 3e3, stdio: "pipe" });
283712
+ const memInfo = execSync39("grep MemTotal /proc/meminfo", { encoding: "utf8", timeout: 3e3, stdio: "pipe" });
283214
283713
  const memKB = parseInt(memInfo.match(/(\d+)/)?.[1] ?? "0", 10);
283215
283714
  return { isJetson: true, model, totalMemGB: memKB / 1024 / 1024 };
283216
283715
  }
@@ -283244,7 +283743,7 @@ function detectPersonaPlexCapability() {
283244
283743
  };
283245
283744
  }
283246
283745
  try {
283247
- const nvsmi = execSync37("nvidia-smi --query-gpu=name,memory.total --format=csv,noheader,nounits", {
283746
+ const nvsmi = execSync39("nvidia-smi --query-gpu=name,memory.total --format=csv,noheader,nounits", {
283248
283747
  encoding: "utf8",
283249
283748
  timeout: 5e3,
283250
283749
  stdio: "pipe"
@@ -283256,7 +283755,7 @@ function detectPersonaPlexCapability() {
283256
283755
  return { ...fail2(`GPU has ${vramGB.toFixed(1)}GB VRAM (need \u22658GB)`), gpuName: gpuName ?? "", vramGB };
283257
283756
  }
283258
283757
  try {
283259
- execSync37('python3 -c "import torch; assert torch.cuda.is_available()"', {
283758
+ execSync39('python3 -c "import torch; assert torch.cuda.is_available()"', {
283260
283759
  timeout: 1e4,
283261
283760
  stdio: "pipe"
283262
283761
  });
@@ -283329,7 +283828,7 @@ async function installPersonaPlex(onInfo, weightTier) {
283329
283828
  mkdirSync20(PERSONAPLEX_DIR, { recursive: true });
283330
283829
  let arch2 = "";
283331
283830
  try {
283332
- arch2 = execSync37("uname -m", { encoding: "utf8", timeout: 3e3, stdio: "pipe" }).trim();
283831
+ arch2 = execSync39("uname -m", { encoding: "utf8", timeout: 3e3, stdio: "pipe" }).trim();
283333
283832
  } catch {
283334
283833
  }
283335
283834
  const isAarch64 = arch2 === "aarch64" || arch2 === "arm64";
@@ -283350,16 +283849,16 @@ async function installPersonaPlex(onInfo, weightTier) {
283350
283849
  log22("Checking system dependencies (libopus)...");
283351
283850
  try {
283352
283851
  if (process.platform === "linux") {
283353
- execSync37("dpkg -l libopus-dev 2>/dev/null || sudo apt-get install -y libopus-dev", { timeout: 3e4, stdio: "pipe" });
283852
+ execSync39("dpkg -l libopus-dev 2>/dev/null || sudo apt-get install -y libopus-dev", { timeout: 3e4, stdio: "pipe" });
283354
283853
  } else if (process.platform === "darwin") {
283355
- execSync37("brew list opus 2>/dev/null || brew install opus", { timeout: 6e4, stdio: "pipe" });
283854
+ execSync39("brew list opus 2>/dev/null || brew install opus", { timeout: 6e4, stdio: "pipe" });
283356
283855
  }
283357
283856
  } catch {
283358
283857
  }
283359
283858
  if (isAarch64) {
283360
283859
  log22("ARM64: Checking Rust toolchain for sphn build...");
283361
283860
  try {
283362
- execSync37("rustc --version", { timeout: 5e3, stdio: "pipe" });
283861
+ execSync39("rustc --version", { timeout: 5e3, stdio: "pipe" });
283363
283862
  } catch {
283364
283863
  log22("ARM64: Installing Rust toolchain (needed for sphn audio codec)...");
283365
283864
  try {
@@ -283432,7 +283931,7 @@ async function installPersonaPlex(onInfo, weightTier) {
283432
283931
  }
283433
283932
  const serverPy = join63(venvDir, "lib", `python3.${process.versions.node ? "12" : "10"}`, "site-packages", "moshi", "server.py");
283434
283933
  try {
283435
- const sitePackages = execSync37(`"${python}" -c "import moshi, os; print(os.path.dirname(moshi.__file__))"`, {
283934
+ const sitePackages = execSync39(`"${python}" -c "import moshi, os; print(os.path.dirname(moshi.__file__))"`, {
283436
283935
  encoding: "utf8",
283437
283936
  timeout: 5e3,
283438
283937
  stdio: "pipe"
@@ -283449,7 +283948,7 @@ async function installPersonaPlex(onInfo, weightTier) {
283449
283948
  } catch {
283450
283949
  }
283451
283950
  try {
283452
- const sitePackages = execSync37(`"${python}" -c "import moshi, os; print(os.path.dirname(moshi.__file__))"`, {
283951
+ const sitePackages = execSync39(`"${python}" -c "import moshi, os; print(os.path.dirname(moshi.__file__))"`, {
283453
283952
  encoding: "utf8",
283454
283953
  timeout: 5e3,
283455
283954
  stdio: "pipe"
@@ -283553,7 +284052,7 @@ $2if filename.endswith(".safetensors"):`
283553
284052
  } catch {
283554
284053
  }
283555
284054
  try {
283556
- const sitePackages2 = execSync37(`"${python}" -c "import moshi, os; print(os.path.dirname(moshi.__file__))"`, {
284055
+ const sitePackages2 = execSync39(`"${python}" -c "import moshi, os; print(os.path.dirname(moshi.__file__))"`, {
283557
284056
  encoding: "utf8",
283558
284057
  timeout: 5e3,
283559
284058
  stdio: "pipe"
@@ -283688,14 +284187,14 @@ async function startPersonaPlexDaemon(onInfo) {
283688
284187
  if (tier === "nf4-distilled") {
283689
284188
  log22(`Weight tier: ${tier} \u2014 distilled NF4 (90% token match, ${repoInfo.sizeGB}GB)...`);
283690
284189
  try {
283691
- const weightPath = execSync37(
284190
+ const weightPath = execSync39(
283692
284191
  `"${venvPython2}" -c "from huggingface_hub import hf_hub_download; print(hf_hub_download('${repoInfo.repo}', '${repoInfo.file}', token=False))"`,
283693
284192
  { encoding: "utf8", timeout: 6e4, stdio: "pipe" }
283694
284193
  ).trim();
283695
284194
  if (existsSync46(weightPath)) {
283696
284195
  if (!existsSync46(cachedBf16)) {
283697
284196
  log22("Converting .pt checkpoint to safetensors (one-time)...");
283698
- execSync37(
284197
+ execSync39(
283699
284198
  `"${venvPython2}" -c "
283700
284199
  import torch; from safetensors.torch import save_file
283701
284200
  state = torch.load('${weightPath}', map_location='cpu', weights_only=True)
@@ -283727,13 +284226,13 @@ print('Converted')
283727
284226
  }
283728
284227
  }
283729
284228
  try {
283730
- const weightPath = execSync37(
284229
+ const weightPath = execSync39(
283731
284230
  `"${venvPython2}" -c "from huggingface_hub import hf_hub_download; print(hf_hub_download('${repoInfo.repo}', '${repoInfo.file}'${repoInfo.needsToken ? "" : ", token=False"}))"`,
283732
284231
  { encoding: "utf8", timeout: 3e4, stdio: "pipe" }
283733
284232
  ).trim();
283734
284233
  if (existsSync46(dequantScript) && existsSync46(weightPath)) {
283735
284234
  try {
283736
- execSync37(
284235
+ execSync39(
283737
284236
  `"${venvPython2}" "${dequantScript}" --input "${weightPath}" --output "${cachedBf16}"`,
283738
284237
  { timeout: 3e5, stdio: "pipe" }
283739
284238
  );
@@ -283746,7 +284245,7 @@ print('Converted')
283746
284245
  }
283747
284246
  }
283748
284247
  try {
283749
- const mimiPath = execSync37(
284248
+ const mimiPath = execSync39(
283750
284249
  `"${venvPython2}" -c "from huggingface_hub import hf_hub_download; print(hf_hub_download('${repoInfo.repo}', 'tokenizer-e351c8d8-checkpoint125.safetensors', token=False))"`,
283751
284250
  { encoding: "utf8", timeout: 3e4, stdio: "pipe" }
283752
284251
  ).trim();
@@ -283754,7 +284253,7 @@ print('Converted')
283754
284253
  } catch {
283755
284254
  }
283756
284255
  try {
283757
- const tokPath = execSync37(
284256
+ const tokPath = execSync39(
283758
284257
  `"${venvPython2}" -c "from huggingface_hub import hf_hub_download; print(hf_hub_download('${repoInfo.repo}', 'tokenizer_spm_32k_3.model', token=False))"`,
283759
284258
  { encoding: "utf8", timeout: 3e4, stdio: "pipe" }
283760
284259
  ).trim();
@@ -283778,7 +284277,7 @@ print('Converted')
283778
284277
  }
283779
284278
  if (!ollamaModel) ollamaModel = "qwen3.5:4b";
283780
284279
  try {
283781
- const ollamaCheck = execSync37("curl -s http://localhost:11434/api/tags", {
284280
+ const ollamaCheck = execSync39("curl -s http://localhost:11434/api/tags", {
283782
284281
  timeout: 3e3,
283783
284282
  stdio: "pipe",
283784
284283
  encoding: "utf8"
@@ -283852,7 +284351,7 @@ print('Converted')
283852
284351
  return null;
283853
284352
  }
283854
284353
  try {
283855
- execSync37(`curl -sk -o /dev/null -w "%{http_code}" https://127.0.0.1:${PORT}/`, {
284354
+ execSync39(`curl -sk -o /dev/null -w "%{http_code}" https://127.0.0.1:${PORT}/`, {
283856
284355
  timeout: 3e3,
283857
284356
  stdio: "pipe",
283858
284357
  encoding: "utf8"
@@ -283875,7 +284374,7 @@ function stopPersonaPlex() {
283875
284374
  if (isNaN(pid) || pid <= 0) return;
283876
284375
  try {
283877
284376
  if (process.platform === "win32") {
283878
- execSync37(`taskkill /F /PID ${pid}`, { timeout: 5e3, stdio: "ignore" });
284377
+ execSync39(`taskkill /F /PID ${pid}`, { timeout: 5e3, stdio: "ignore" });
283879
284378
  } else {
283880
284379
  process.kill(pid, "SIGTERM");
283881
284380
  }
@@ -284179,7 +284678,7 @@ __export(setup_exports, {
284179
284678
  updateOllama: () => updateOllama
284180
284679
  });
284181
284680
  import * as readline from "node:readline";
284182
- import { execSync as execSync38, spawn as spawn21, exec as exec4 } from "node:child_process";
284681
+ import { execSync as execSync40, spawn as spawn21, exec as exec4 } from "node:child_process";
284183
284682
  import { promisify as promisify7 } from "node:util";
284184
284683
  import { existsSync as existsSync47, writeFileSync as writeFileSync22, readFileSync as readFileSync37, appendFileSync as appendFileSync2, mkdirSync as mkdirSync21 } from "node:fs";
284185
284684
  import { join as join64 } from "node:path";
@@ -284217,7 +284716,7 @@ function detectSystemSpecs() {
284217
284716
  let gpuVramGB = 0;
284218
284717
  let gpuName = "";
284219
284718
  try {
284220
- const memInfo = execSync38("free -b 2>/dev/null || sysctl -n hw.memsize 2>/dev/null", {
284719
+ const memInfo = execSync40("free -b 2>/dev/null || sysctl -n hw.memsize 2>/dev/null", {
284221
284720
  encoding: "utf8",
284222
284721
  timeout: 5e3
284223
284722
  });
@@ -284237,7 +284736,7 @@ function detectSystemSpecs() {
284237
284736
  } catch {
284238
284737
  }
284239
284738
  try {
284240
- const nvidiaSmi = execSync38(
284739
+ const nvidiaSmi = execSync40(
284241
284740
  "nvidia-smi --query-gpu=memory.total,name --format=csv,noheader,nounits 2>/dev/null",
284242
284741
  { encoding: "utf8", timeout: 5e3 }
284243
284742
  );
@@ -284411,7 +284910,7 @@ function ensureCurl() {
284411
284910
  for (const s2 of strategies) {
284412
284911
  if (hasCmd(s2.check)) {
284413
284912
  try {
284414
- execSync38(s2.install, { stdio: "inherit", timeout: 12e4 });
284913
+ execSync40(s2.install, { stdio: "inherit", timeout: 12e4 });
284415
284914
  if (hasCmd("curl")) {
284416
284915
  process.stdout.write(` ${c3.green("\u2714")} curl installed via ${s2.label}.
284417
284916
  `);
@@ -284425,7 +284924,7 @@ function ensureCurl() {
284425
284924
  }
284426
284925
  if (plat === "darwin") {
284427
284926
  try {
284428
- execSync38("xcode-select --install", { stdio: "inherit", timeout: 3e5 });
284927
+ execSync40("xcode-select --install", { stdio: "inherit", timeout: 3e5 });
284429
284928
  if (hasCmd("curl")) return true;
284430
284929
  } catch {
284431
284930
  }
@@ -284459,7 +284958,7 @@ function installOllamaLinux() {
284459
284958
 
284460
284959
  `);
284461
284960
  try {
284462
- execSync38("curl -fsSL https://ollama.com/install.sh | sh", {
284961
+ execSync40("curl -fsSL https://ollama.com/install.sh | sh", {
284463
284962
  stdio: "inherit",
284464
284963
  timeout: 3e5
284465
284964
  });
@@ -284487,7 +284986,7 @@ async function installOllamaMac(_rl) {
284487
284986
 
284488
284987
  `);
284489
284988
  try {
284490
- execSync38(
284989
+ execSync40(
284491
284990
  '/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"',
284492
284991
  { stdio: "inherit", timeout: 6e5 }
284493
284992
  );
@@ -284523,7 +285022,7 @@ async function installOllamaMac(_rl) {
284523
285022
 
284524
285023
  `);
284525
285024
  try {
284526
- execSync38("brew install ollama", {
285025
+ execSync40("brew install ollama", {
284527
285026
  stdio: "inherit",
284528
285027
  timeout: 3e5
284529
285028
  });
@@ -284550,7 +285049,7 @@ function installOllamaWindows() {
284550
285049
 
284551
285050
  `);
284552
285051
  try {
284553
- execSync38('powershell -Command "irm https://ollama.com/install.ps1 | iex"', {
285052
+ execSync40('powershell -Command "irm https://ollama.com/install.ps1 | iex"', {
284554
285053
  stdio: "inherit",
284555
285054
  timeout: 3e5
284556
285055
  });
@@ -284630,7 +285129,7 @@ async function ensureOllamaRunning(backendUrl, rl) {
284630
285129
  }
284631
285130
  function getOllamaVersion() {
284632
285131
  try {
284633
- const out = execSync38("ollama --version", { encoding: "utf8", timeout: 5e3 });
285132
+ const out = execSync40("ollama --version", { encoding: "utf8", timeout: 5e3 });
284634
285133
  const match = out.match(/(\d+\.\d+\.\d+)/);
284635
285134
  return match ? match[1] : null;
284636
285135
  } catch {
@@ -284676,7 +285175,7 @@ function updateOllama() {
284676
285175
  return false;
284677
285176
  }
284678
285177
  try {
284679
- execSync38("curl -fsSL https://ollama.com/install.sh | sh", {
285178
+ execSync40("curl -fsSL https://ollama.com/install.sh | sh", {
284680
285179
  stdio: "inherit",
284681
285180
  timeout: 3e5
284682
285181
  });
@@ -284687,7 +285186,7 @@ function updateOllama() {
284687
285186
  }
284688
285187
  function pullModelWithAutoUpdate(tag) {
284689
285188
  try {
284690
- execSync38(`ollama pull ${tag}`, {
285189
+ execSync40(`ollama pull ${tag}`, {
284691
285190
  stdio: "inherit",
284692
285191
  timeout: 36e5
284693
285192
  // 1 hour max
@@ -284707,7 +285206,7 @@ function pullModelWithAutoUpdate(tag) {
284707
285206
 
284708
285207
  `);
284709
285208
  try {
284710
- execSync38("curl -fsSL https://ollama.com/install.sh | sh", {
285209
+ execSync40("curl -fsSL https://ollama.com/install.sh | sh", {
284711
285210
  stdio: "inherit",
284712
285211
  timeout: 3e5
284713
285212
  // 5 min max for install
@@ -284718,7 +285217,7 @@ function pullModelWithAutoUpdate(tag) {
284718
285217
  process.stdout.write(` ${c3.cyan("\u25CF")} Retrying pull of ${c3.bold(tag)}...
284719
285218
 
284720
285219
  `);
284721
- execSync38(`ollama pull ${tag}`, {
285220
+ execSync40(`ollama pull ${tag}`, {
284722
285221
  stdio: "inherit",
284723
285222
  timeout: 36e5
284724
285223
  });
@@ -284807,7 +285306,7 @@ function ensurePython3() {
284807
285306
  if (plat === "darwin") {
284808
285307
  if (hasCmd("brew")) {
284809
285308
  try {
284810
- execSync38("brew install python3", { stdio: "inherit", timeout: 3e5 });
285309
+ execSync40("brew install python3", { stdio: "inherit", timeout: 3e5 });
284811
285310
  if (hasCmd("python3")) {
284812
285311
  process.stdout.write(` ${c3.green("\u2714")} Python3 installed via Homebrew.
284813
285312
  `);
@@ -284820,7 +285319,7 @@ function ensurePython3() {
284820
285319
  for (const s2 of strategies) {
284821
285320
  if (hasCmd(s2.check)) {
284822
285321
  try {
284823
- execSync38(s2.install, { stdio: "inherit", timeout: 12e4 });
285322
+ execSync40(s2.install, { stdio: "inherit", timeout: 12e4 });
284824
285323
  if (hasCmd("python3") || hasCmd("python")) {
284825
285324
  process.stdout.write(` ${c3.green("\u2714")} Python3 installed via ${s2.label}.
284826
285325
  `);
@@ -284836,11 +285335,11 @@ function ensurePython3() {
284836
285335
  }
284837
285336
  function checkPythonVenv() {
284838
285337
  try {
284839
- execSync38("python3 -m venv --help", { stdio: "pipe", timeout: 5e3 });
285338
+ execSync40("python3 -m venv --help", { stdio: "pipe", timeout: 5e3 });
284840
285339
  return true;
284841
285340
  } catch {
284842
285341
  try {
284843
- execSync38("python -m venv --help", { stdio: "pipe", timeout: 5e3 });
285342
+ execSync40("python -m venv --help", { stdio: "pipe", timeout: 5e3 });
284844
285343
  return true;
284845
285344
  } catch {
284846
285345
  return false;
@@ -284859,7 +285358,7 @@ function ensurePythonVenv() {
284859
285358
  for (const s2 of strategies) {
284860
285359
  if (hasCmd(s2.check)) {
284861
285360
  try {
284862
- execSync38(s2.install, { stdio: "inherit", timeout: 12e4 });
285361
+ execSync40(s2.install, { stdio: "inherit", timeout: 12e4 });
284863
285362
  if (checkPythonVenv()) {
284864
285363
  process.stdout.write(` ${c3.green("\u2714")} python3-venv installed via ${s2.label}.
284865
285364
  `);
@@ -285287,7 +285786,7 @@ async function doSetup(config, rl) {
285287
285786
  const modelfilePath = join64(modelDir2, `Modelfile.${customName}`);
285288
285787
  writeFileSync22(modelfilePath, modelfileContent + "\n", "utf8");
285289
285788
  process.stdout.write(` ${c3.dim("Creating model...")} `);
285290
- execSync38(`ollama create ${customName} -f ${modelfilePath}`, {
285789
+ execSync40(`ollama create ${customName} -f ${modelfilePath}`, {
285291
285790
  stdio: "pipe",
285292
285791
  timeout: 12e4
285293
285792
  });
@@ -285338,7 +285837,7 @@ function isFirstRun() {
285338
285837
  function hasCmd(cmd) {
285339
285838
  try {
285340
285839
  const whichCmd = process.platform === "win32" ? `where ${cmd}` : `which ${cmd}`;
285341
- execSync38(whichCmd, { stdio: "pipe", timeout: 3e3 });
285840
+ execSync40(whichCmd, { stdio: "pipe", timeout: 3e3 });
285342
285841
  return true;
285343
285842
  } catch {
285344
285843
  return false;
@@ -285350,7 +285849,7 @@ function detectPkgManager() {
285350
285849
  if (hasCmd("choco")) return "choco";
285351
285850
  if (hasCmd("winget")) return "winget";
285352
285851
  try {
285353
- execSync38(
285852
+ execSync40(
285354
285853
  `powershell -NoProfile -Command "Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))"`,
285355
285854
  { stdio: "pipe", timeout: 12e4 }
285356
285855
  );
@@ -285362,7 +285861,7 @@ function detectPkgManager() {
285362
285861
  if (plat === "darwin") {
285363
285862
  if (hasCmd("brew")) return "brew";
285364
285863
  try {
285365
- execSync38(
285864
+ execSync40(
285366
285865
  '/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"',
285367
285866
  { stdio: "pipe", timeout: 3e5, env: { ...process.env, NONINTERACTIVE: "1" } }
285368
285867
  );
@@ -285382,7 +285881,7 @@ function getVenvDir() {
285382
285881
  }
285383
285882
  function hasVenvModule() {
285384
285883
  try {
285385
- execSync38("python3 -m venv --help", { stdio: "pipe", timeout: 5e3 });
285884
+ execSync40("python3 -m venv --help", { stdio: "pipe", timeout: 5e3 });
285386
285885
  return true;
285387
285886
  } catch {
285388
285887
  return false;
@@ -285406,8 +285905,8 @@ function ensureVenv(log22) {
285406
285905
  try {
285407
285906
  mkdirSync21(join64(homedir18(), ".open-agents"), { recursive: true });
285408
285907
  const pyCmd = hasCmd(pythonCmd) ? pythonCmd : "python3";
285409
- execSync38(`${pyCmd} -m venv "${venvDir}"`, { stdio: "pipe", timeout: 3e4 });
285410
- execSync38(`"${pipPath}" install --upgrade pip`, {
285908
+ execSync40(`${pyCmd} -m venv "${venvDir}"`, { stdio: "pipe", timeout: 3e4 });
285909
+ execSync40(`"${pipPath}" install --upgrade pip`, {
285411
285910
  stdio: "pipe",
285412
285911
  timeout: 6e4
285413
285912
  });
@@ -285420,7 +285919,7 @@ function ensureVenv(log22) {
285420
285919
  }
285421
285920
  function trySudoPasswordless(cmd, timeoutMs = 12e4) {
285422
285921
  try {
285423
- execSync38(`sudo -n ${cmd}`, {
285922
+ execSync40(`sudo -n ${cmd}`, {
285424
285923
  stdio: "pipe",
285425
285924
  timeout: timeoutMs,
285426
285925
  env: { ...process.env, DEBIAN_FRONTEND: "noninteractive" }
@@ -285433,7 +285932,7 @@ function trySudoPasswordless(cmd, timeoutMs = 12e4) {
285433
285932
  function runWithSudo(cmd, password, timeoutMs = 12e4) {
285434
285933
  try {
285435
285934
  const escaped = cmd.replace(/'/g, "'\\''");
285436
- execSync38(`sudo -S bash -c '${escaped}'`, {
285935
+ execSync40(`sudo -S bash -c '${escaped}'`, {
285437
285936
  input: password + "\n",
285438
285937
  stdio: ["pipe", "pipe", "pipe"],
285439
285938
  timeout: timeoutMs,
@@ -285527,7 +286026,7 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
285527
286026
  let winNeedsElevation = false;
285528
286027
  if (process.platform === "win32") {
285529
286028
  try {
285530
- execSync38("net session", { stdio: "pipe", timeout: 3e3 });
286029
+ execSync40("net session", { stdio: "pipe", timeout: 3e3 });
285531
286030
  } catch {
285532
286031
  winNeedsElevation = true;
285533
286032
  log22(`Installing ${labels} via ${pm2} (requires admin \u2014 UAC prompt will appear)...`);
@@ -285574,12 +286073,12 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
285574
286073
  if (needsSudo) {
285575
286074
  await sudoInstall(installCmd, getPassword, log22, cachedPasswordRef, 18e4);
285576
286075
  } else if (winNeedsElevation) {
285577
- execSync38(
286076
+ execSync40(
285578
286077
  `powershell -NoProfile -Command "Start-Process -FilePath 'cmd.exe' -ArgumentList '/c ${installCmd.replace(/'/g, "''")}' -Verb RunAs -Wait"`,
285579
286078
  { stdio: "pipe", timeout: 18e4 }
285580
286079
  );
285581
286080
  } else {
285582
- execSync38(installCmd, { stdio: "pipe", timeout: 18e4 });
286081
+ execSync40(installCmd, { stdio: "pipe", timeout: 18e4 });
285583
286082
  }
285584
286083
  } catch (e2) {
285585
286084
  const stderr = e2.stderr?.toString?.()?.trim?.() ?? "";
@@ -285592,7 +286091,7 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
285592
286091
  if (!hasCmd(d2.binary) && pipPkg) {
285593
286092
  try {
285594
286093
  const pipCmd = process.platform === "win32" ? `pip install ${pipPkg}` : `pip3 install ${pipPkg}`;
285595
- execSync38(pipCmd, { stdio: "pipe", timeout: 12e4 });
286094
+ execSync40(pipCmd, { stdio: "pipe", timeout: 12e4 });
285596
286095
  lastError = "";
285597
286096
  } catch (e2) {
285598
286097
  const stderr = e2.stderr?.toString?.()?.trim?.() ?? "";
@@ -285604,7 +286103,7 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
285604
286103
  }
285605
286104
  if (process.platform === "win32" && !hasCmd(d2.binary)) {
285606
286105
  try {
285607
- const freshPath = execSync38(
286106
+ const freshPath = execSync40(
285608
286107
  `powershell -NoProfile -Command "[System.Environment]::GetEnvironmentVariable('Path','Machine') + ';' + [System.Environment]::GetEnvironmentVariable('Path','User')"`,
285609
286108
  { encoding: "utf8", timeout: 5e3, stdio: "pipe" }
285610
286109
  ).trim();
@@ -285650,7 +286149,7 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
285650
286149
  const venvCmds = {
285651
286150
  apt: () => {
285652
286151
  try {
285653
- const pyVer = execSync38(
286152
+ const pyVer = execSync40(
285654
286153
  `python3 -c "import sys; print(f'{sys.version_info.major}.{sys.version_info.minor}')"`,
285655
286154
  { encoding: "utf8", stdio: "pipe", timeout: 5e3 }
285656
286155
  ).trim();
@@ -285682,12 +286181,12 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
285682
286181
  const venvPip2 = join64(venvBin, "pip");
285683
286182
  log22("Installing moondream-station in ~/.open-agents/venv...");
285684
286183
  try {
285685
- execSync38(`"${venvPip2}" install moondream-station`, { stdio: "pipe", timeout: 3e5 });
286184
+ execSync40(`"${venvPip2}" install moondream-station`, { stdio: "pipe", timeout: 3e5 });
285686
286185
  if (existsSync47(venvMoondream)) {
285687
286186
  log22("moondream-station installed successfully.");
285688
286187
  } else {
285689
286188
  try {
285690
- const check = execSync38(`"${venvPip2}" show moondream-station`, { encoding: "utf8", stdio: "pipe", timeout: 5e3 });
286189
+ const check = execSync40(`"${venvPip2}" show moondream-station`, { encoding: "utf8", stdio: "pipe", timeout: 5e3 });
285691
286190
  if (check.includes("moondream")) {
285692
286191
  log22("moondream-station package installed.");
285693
286192
  }
@@ -285704,7 +286203,7 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
285704
286203
  const venvPip2 = join64(venvBin, isWin2 ? "pip.exe" : "pip");
285705
286204
  let ocrStackInstalled = false;
285706
286205
  try {
285707
- execSync38(
286206
+ execSync40(
285708
286207
  `"${venvPython2}" -c "import cv2, pytesseract, numpy, PIL"`,
285709
286208
  { stdio: "pipe", timeout: 1e4 }
285710
286209
  );
@@ -285715,12 +286214,12 @@ async function ensureVisionDeps(onInfo, getSudoPassword) {
285715
286214
  const ocrPackages = "pytesseract Pillow opencv-python-headless numpy";
285716
286215
  log22("Installing OCR Python stack (pytesseract, OpenCV, Pillow, numpy)...");
285717
286216
  try {
285718
- execSync38(
286217
+ execSync40(
285719
286218
  `"${venvPip2}" install ${ocrPackages}`,
285720
286219
  { stdio: "pipe", timeout: 3e5 }
285721
286220
  );
285722
286221
  try {
285723
- execSync38(
286222
+ execSync40(
285724
286223
  `"${venvPython2}" -c "import cv2, pytesseract, numpy, PIL"`,
285725
286224
  { stdio: "pipe", timeout: 1e4 }
285726
286225
  );
@@ -285756,7 +286255,7 @@ function ensureCloudflaredBackground(onInfo) {
285756
286255
  const archMap = { x64: "amd64", arm64: "arm64", arm: "arm" };
285757
286256
  const cfArch = archMap[arch2] ?? "amd64";
285758
286257
  try {
285759
- execSync38(
286258
+ execSync40(
285760
286259
  `curl -fsSL "https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-${cfArch}" -o /tmp/cloudflared && chmod +x /tmp/cloudflared && mkdir -p "${homedir18()}/.local/bin" && mv /tmp/cloudflared "${homedir18()}/.local/bin/cloudflared"`,
285761
286260
  { stdio: "pipe", timeout: 6e4 }
285762
286261
  );
@@ -285770,7 +286269,7 @@ function ensureCloudflaredBackground(onInfo) {
285770
286269
  } catch {
285771
286270
  }
285772
286271
  try {
285773
- execSync38(
286272
+ execSync40(
285774
286273
  `curl -fsSL "https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-${cfArch}" -o /tmp/cloudflared && chmod +x /tmp/cloudflared && sudo mv /tmp/cloudflared /usr/local/bin/cloudflared 2>/dev/null`,
285775
286274
  { stdio: "pipe", timeout: 6e4 }
285776
286275
  );
@@ -285782,7 +286281,7 @@ function ensureCloudflaredBackground(onInfo) {
285782
286281
  }
285783
286282
  } else if (os8 === "darwin") {
285784
286283
  try {
285785
- execSync38("brew install cloudflared", { stdio: "pipe", timeout: 12e4 });
286284
+ execSync40("brew install cloudflared", { stdio: "pipe", timeout: 12e4 });
285786
286285
  if (hasCmd("cloudflared")) {
285787
286286
  log22("cloudflared installed via Homebrew.");
285788
286287
  return true;
@@ -285862,7 +286361,7 @@ function createExpandedVariant(baseModel, specs, sizeGB, kvBytesPerToken, archMa
285862
286361
  mkdirSync21(modelDir2, { recursive: true });
285863
286362
  const modelfilePath = join64(modelDir2, `Modelfile.${customName}`);
285864
286363
  writeFileSync22(modelfilePath, modelfileContent + "\n", "utf8");
285865
- execSync38(`ollama create ${customName} -f ${modelfilePath}`, {
286364
+ execSync40(`ollama create ${customName} -f ${modelfilePath}`, {
285866
286365
  stdio: "pipe",
285867
286366
  timeout: 12e4
285868
286367
  });
@@ -285948,7 +286447,7 @@ async function ensureExpandedContext(modelName, backendUrl) {
285948
286447
  }
285949
286448
  async function ensureNeovim() {
285950
286449
  try {
285951
- const nvimPath = execSync38("which nvim 2>/dev/null || where nvim 2>nul", {
286450
+ const nvimPath = execSync40("which nvim 2>/dev/null || where nvim 2>nul", {
285952
286451
  encoding: "utf8",
285953
286452
  stdio: "pipe",
285954
286453
  timeout: 5e3
@@ -285969,14 +286468,14 @@ async function ensureNeovim() {
285969
286468
  const url = `https://github.com/neovim/neovim/releases/latest/download/${appImageName}`;
285970
286469
  console.log(` Downloading Neovim (${appImageName})...`);
285971
286470
  try {
285972
- execSync38(`curl -fsSL "${url}" -o "${nvimDest}"`, { stdio: "pipe", timeout: 6e4 });
285973
- execSync38(`chmod +x "${nvimDest}"`, { stdio: "pipe", timeout: 3e3 });
286471
+ execSync40(`curl -fsSL "${url}" -o "${nvimDest}"`, { stdio: "pipe", timeout: 6e4 });
286472
+ execSync40(`chmod +x "${nvimDest}"`, { stdio: "pipe", timeout: 3e3 });
285974
286473
  } catch (err) {
285975
286474
  console.log(` Failed to download Neovim: ${err instanceof Error ? err.message : String(err)}`);
285976
286475
  return null;
285977
286476
  }
285978
286477
  try {
285979
- const ver = execSync38(`"${nvimDest}" --version`, { encoding: "utf8", stdio: "pipe", timeout: 5e3 }).split("\n")[0];
286478
+ const ver = execSync40(`"${nvimDest}" --version`, { encoding: "utf8", stdio: "pipe", timeout: 5e3 }).split("\n")[0];
285980
286479
  console.log(` Installed: ${ver}`);
285981
286480
  } catch {
285982
286481
  console.log(" Warning: nvim binary downloaded but may not work (missing FUSE? Try: nvim --appimage-extract)");
@@ -285991,8 +286490,8 @@ async function ensureNeovim() {
285991
286490
  if (hasCmd("brew")) {
285992
286491
  console.log(" Installing Neovim via Homebrew...");
285993
286492
  try {
285994
- execSync38("brew install neovim", { stdio: "inherit", timeout: 12e4 });
285995
- const nvimPath = execSync38("which nvim", { encoding: "utf8", stdio: "pipe", timeout: 3e3 }).trim();
286493
+ execSync40("brew install neovim", { stdio: "inherit", timeout: 12e4 });
286494
+ const nvimPath = execSync40("which nvim", { encoding: "utf8", stdio: "pipe", timeout: 3e3 }).trim();
285996
286495
  return nvimPath || null;
285997
286496
  } catch {
285998
286497
  console.log(" brew install neovim failed.");
@@ -286006,7 +286505,7 @@ async function ensureNeovim() {
286006
286505
  if (hasCmd("choco")) {
286007
286506
  console.log(" Installing Neovim via Chocolatey...");
286008
286507
  try {
286009
- execSync38("choco install neovim -y", { stdio: "inherit", timeout: 12e4 });
286508
+ execSync40("choco install neovim -y", { stdio: "inherit", timeout: 12e4 });
286010
286509
  return "nvim";
286011
286510
  } catch {
286012
286511
  console.log(" choco install neovim failed.");
@@ -286015,7 +286514,7 @@ async function ensureNeovim() {
286015
286514
  if (hasCmd("winget")) {
286016
286515
  console.log(" Installing Neovim via winget...");
286017
286516
  try {
286018
- execSync38("winget install Neovim.Neovim --accept-source-agreements --accept-package-agreements", {
286517
+ execSync40("winget install Neovim.Neovim --accept-source-agreements --accept-package-agreements", {
286019
286518
  stdio: "inherit",
286020
286519
  timeout: 12e4
286021
286520
  });
@@ -286266,7 +286765,7 @@ var init_drop_panel = __esm({
286266
286765
  import { existsSync as existsSync49, unlinkSync as unlinkSync11 } from "node:fs";
286267
286766
  import { tmpdir as tmpdir11 } from "node:os";
286268
286767
  import { join as join65 } from "node:path";
286269
- import { execSync as execSync39 } from "node:child_process";
286768
+ import { execSync as execSync41 } from "node:child_process";
286270
286769
  function isNeovimActive() {
286271
286770
  return _state !== null && !_state.cleanedUp;
286272
286771
  }
@@ -286283,7 +286782,7 @@ async function startNeovimMode(opts) {
286283
286782
  }
286284
286783
  let nvimPath;
286285
286784
  try {
286286
- nvimPath = execSync39("which nvim 2>/dev/null", { encoding: "utf8" }).trim();
286785
+ nvimPath = execSync41("which nvim 2>/dev/null", { encoding: "utf8" }).trim();
286287
286786
  if (!nvimPath) throw new Error();
286288
286787
  } catch {
286289
286788
  const installed = await ensureNeovim();
@@ -286818,8 +287317,8 @@ async function startDaemon() {
286818
287317
  let oaScript = process.argv[1];
286819
287318
  if (!oaScript) {
286820
287319
  try {
286821
- const { execSync: execSync46 } = await import("node:child_process");
286822
- const whichOa = execSync46("which oa 2>/dev/null || where oa 2>nul", { encoding: "utf8" }).trim();
287320
+ const { execSync: execSync48 } = await import("node:child_process");
287321
+ const whichOa = execSync48("which oa 2>/dev/null || where oa 2>nul", { encoding: "utf8" }).trim();
286823
287322
  if (whichOa) oaScript = whichOa;
286824
287323
  } catch {
286825
287324
  }
@@ -288226,7 +288725,7 @@ __export(voice_exports, {
288226
288725
  import { existsSync as existsSync52, mkdirSync as mkdirSync24, writeFileSync as writeFileSync25, readFileSync as readFileSync40, unlinkSync as unlinkSync13, readdirSync as readdirSync13, statSync as statSync17 } from "node:fs";
288227
288726
  import { join as join68, dirname as dirname22 } from "node:path";
288228
288727
  import { homedir as homedir20, tmpdir as tmpdir12, platform as platform4 } from "node:os";
288229
- import { execSync as execSync40, spawn as nodeSpawn } from "node:child_process";
288728
+ import { execSync as execSync42, spawn as nodeSpawn } from "node:child_process";
288230
288729
  import { createRequire as createRequire2 } from "node:module";
288231
288730
  function sanitizeForTTS(text) {
288232
288731
  return text.replace(/^#{1,6}\s+/gm, "").replace(/\*{1,3}([^*]+)\*{1,3}/g, "$1").replace(/_{1,3}([^_]+)_{1,3}/g, "$1").replace(/~~([^~]+)~~/g, "$1").replace(/`([^`]+)`/g, "$1").replace(/```[\s\S]*?```/g, "").replace(/\[([^\]]+)\]\([^)]+\)/g, "$1").replace(/!\[([^\]]*)\]\([^)]+\)/g, "$1").replace(/^[\s]*[-*+]\s+/gm, "").replace(/^[\s]*\d+\.\s+/gm, "").replace(/^>\s+/gm, "").replace(/^[-*_]{3,}$/gm, "").replace(/\[[ xX]\]\s*/g, "").replace(/[\u{1F600}-\u{1F64F}]/gu, "").replace(/[\u{1F300}-\u{1F5FF}]/gu, "").replace(/[\u{1F680}-\u{1F6FF}]/gu, "").replace(/[\u{1F1E0}-\u{1F1FF}]/gu, "").replace(/[\u{2600}-\u{26FF}]/gu, "").replace(/[\u{2700}-\u{27BF}]/gu, "").replace(/[\u{FE00}-\u{FE0F}]/gu, "").replace(/[\u{1F900}-\u{1F9FF}]/gu, "").replace(/[\u{1FA00}-\u{1FA6F}]/gu, "").replace(/[\u{1FA70}-\u{1FAFF}]/gu, "").replace(/[\u{200D}]/gu, "").replace(/[\u{20E3}]/gu, "").replace(/[✓✔✗✘✕✖⚠️⏸⏹⏵●○◆◇■□▪▫►▼▲◀⬆⬇⬅➡↑↓←→⇐⇒⇑⇓]/g, "").replace(/[─━│┃┌┐└┘├┤┬┴┼╔╗╚╝╠╣╦╩╬⎿⎾▕▏⏐░▒▓█⠀-⣿]/g, "").replace(/\s{2,}/g, " ").trim();
@@ -289914,7 +290413,7 @@ var init_voice = __esm({
289914
290413
  }
289915
290414
  for (const player of ["paplay", "pw-play", "aplay"]) {
289916
290415
  try {
289917
- execSync40(`which ${player}`, { stdio: "pipe" });
290416
+ execSync42(`which ${player}`, { stdio: "pipe" });
289918
290417
  return [player, path5];
289919
290418
  } catch {
289920
290419
  }
@@ -289942,7 +290441,7 @@ var init_voice = __esm({
289942
290441
  if (this.python3Path) return this.python3Path;
289943
290442
  for (const bin of ["python3", "python"]) {
289944
290443
  try {
289945
- const path5 = execSync40(`which ${bin}`, { stdio: "pipe", timeout: 5e3 }).toString().trim();
290444
+ const path5 = execSync42(`which ${bin}`, { stdio: "pipe", timeout: 5e3 }).toString().trim();
289946
290445
  if (path5) {
289947
290446
  this.python3Path = path5;
289948
290447
  return path5;
@@ -290004,7 +290503,7 @@ var init_voice = __esm({
290004
290503
  return false;
290005
290504
  }
290006
290505
  try {
290007
- execSync40(`${py} -c "import mlx_audio"`, { stdio: "pipe", timeout: 1e4 });
290506
+ execSync42(`${py} -c "import mlx_audio"`, { stdio: "pipe", timeout: 1e4 });
290008
290507
  this.mlxInstalled = true;
290009
290508
  return true;
290010
290509
  } catch {
@@ -290067,14 +290566,14 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`
290067
290566
  `tts_gen.main(["--model", ${JSON.stringify(mlxModelId)}, "--text", text, "--voice", ${JSON.stringify(mlxVoice)}, "--lang_code", ${JSON.stringify(mlxLangCode)}, "--audio_path", ${JSON.stringify(wavPath)}])`
290068
290567
  ].join("; ");
290069
290568
  try {
290070
- execSync40(
290569
+ execSync42(
290071
290570
  `${py} -c ${JSON.stringify(pyScript)} ${JSON.stringify(JSON.stringify(cleaned))}`,
290072
290571
  { stdio: "pipe", timeout: 6e4, cwd: tmpdir12() }
290073
290572
  );
290074
290573
  } catch (err) {
290075
290574
  try {
290076
290575
  const safeText = cleaned.replace(/'/g, "'\\''");
290077
- execSync40(
290576
+ execSync42(
290078
290577
  `${py} -m mlx_audio.tts.generate --model ${mlxModelId} --text '${safeText}' --voice ${mlxVoice} --lang_code ${mlxLangCode} --audio_path ${JSON.stringify(wavPath)}`,
290079
290578
  { stdio: "pipe", timeout: 6e4, cwd: tmpdir12() }
290080
290579
  );
@@ -290141,14 +290640,14 @@ Error: ${err2 instanceof Error ? err2.message : String(err2)}`
290141
290640
  `tts_gen.main(["--model", ${JSON.stringify(mlxModelId)}, "--text", text, "--voice", ${JSON.stringify(mlxVoice)}, "--lang_code", ${JSON.stringify(mlxLangCode)}, "--audio_path", ${JSON.stringify(wavPath)}])`
290142
290641
  ].join("; ");
290143
290642
  try {
290144
- execSync40(
290643
+ execSync42(
290145
290644
  `${py} -c ${JSON.stringify(pyScript)} ${JSON.stringify(JSON.stringify(cleaned))}`,
290146
290645
  { stdio: "pipe", timeout: 6e4, cwd: tmpdir12() }
290147
290646
  );
290148
290647
  } catch {
290149
290648
  try {
290150
290649
  const safeText = cleaned.replace(/'/g, "'\\''");
290151
- execSync40(
290650
+ execSync42(
290152
290651
  `${py} -m mlx_audio.tts.generate --model ${mlxModelId} --text '${safeText}' --voice ${mlxVoice} --lang_code ${mlxLangCode} --audio_path ${JSON.stringify(wavPath)}`,
290153
290652
  { stdio: "pipe", timeout: 6e4, cwd: tmpdir12() }
290154
290653
  );
@@ -295663,7 +296162,7 @@ async function handlePeerEndpoint(peerId, authKey, ctx3, local) {
295663
296162
  }
295664
296163
  }
295665
296164
  async function handleParallel(arg, ctx3) {
295666
- const { execSync: execSync46 } = await import("node:child_process");
296165
+ const { execSync: execSync48 } = await import("node:child_process");
295667
296166
  const baseUrl = ctx3.config.backendUrl || "http://localhost:11434";
295668
296167
  const isRemote = ctx3.config.backendType === "nexus";
295669
296168
  if (isRemote) {
@@ -295687,7 +296186,7 @@ async function handleParallel(arg, ctx3) {
295687
296186
  }
295688
296187
  let systemdVal = "";
295689
296188
  try {
295690
- const out = execSync46("systemctl show ollama.service -p Environment 2>/dev/null || true", { encoding: "utf8" });
296189
+ const out = execSync48("systemctl show ollama.service -p Environment 2>/dev/null || true", { encoding: "utf8" });
295691
296190
  const match = out.match(/OLLAMA_NUM_PARALLEL=(\d+)/);
295692
296191
  if (match) systemdVal = match[1];
295693
296192
  } catch {
@@ -295715,7 +296214,7 @@ async function handleParallel(arg, ctx3) {
295715
296214
  }
295716
296215
  const isSystemd = (() => {
295717
296216
  try {
295718
- const out = execSync46("systemctl is-active ollama.service 2>/dev/null", { encoding: "utf8" }).trim();
296217
+ const out = execSync48("systemctl is-active ollama.service 2>/dev/null", { encoding: "utf8" }).trim();
295719
296218
  return out === "active" || out === "inactive";
295720
296219
  } catch {
295721
296220
  return false;
@@ -295729,10 +296228,10 @@ async function handleParallel(arg, ctx3) {
295729
296228
  const overrideContent = `[Service]
295730
296229
  Environment="OLLAMA_NUM_PARALLEL=${n2}"
295731
296230
  `;
295732
- execSync46(`sudo mkdir -p ${overrideDir}`, { stdio: "pipe" });
295733
- execSync46(`echo '${overrideContent}' | sudo tee ${overrideFile} > /dev/null`, { stdio: "pipe" });
295734
- execSync46("sudo systemctl daemon-reload", { stdio: "pipe" });
295735
- execSync46("sudo systemctl restart ollama.service", { stdio: "pipe" });
296231
+ execSync48(`sudo mkdir -p ${overrideDir}`, { stdio: "pipe" });
296232
+ execSync48(`echo '${overrideContent}' | sudo tee ${overrideFile} > /dev/null`, { stdio: "pipe" });
296233
+ execSync48("sudo systemctl daemon-reload", { stdio: "pipe" });
296234
+ execSync48("sudo systemctl restart ollama.service", { stdio: "pipe" });
295736
296235
  let ready = false;
295737
296236
  for (let i2 = 0; i2 < 30 && !ready; i2++) {
295738
296237
  await new Promise((r2) => setTimeout(r2, 500));
@@ -295758,7 +296257,7 @@ Environment="OLLAMA_NUM_PARALLEL=${n2}"
295758
296257
  renderInfo(`Setting OLLAMA_NUM_PARALLEL=${n2}...`);
295759
296258
  try {
295760
296259
  try {
295761
- execSync46("pkill -f 'ollama serve' 2>/dev/null || true", { stdio: "pipe" });
296260
+ execSync48("pkill -f 'ollama serve' 2>/dev/null || true", { stdio: "pipe" });
295762
296261
  } catch {
295763
296262
  }
295764
296263
  await new Promise((r2) => setTimeout(r2, 1e3));
@@ -296810,18 +297309,18 @@ async function showExposeDashboard(gateway, rl, ctx3) {
296810
297309
  const cmd = `/endpoint ${id} --auth ${gateway.authKey ?? ""}`;
296811
297310
  let copied = false;
296812
297311
  try {
296813
- const { execSync: execSync46 } = __require("node:child_process");
297312
+ const { execSync: execSync48 } = __require("node:child_process");
296814
297313
  const platform6 = process.platform;
296815
297314
  if (platform6 === "darwin") {
296816
- execSync46("pbcopy", { input: cmd, timeout: 3e3 });
297315
+ execSync48("pbcopy", { input: cmd, timeout: 3e3 });
296817
297316
  copied = true;
296818
297317
  } else if (platform6 === "win32") {
296819
- execSync46("clip", { input: cmd, timeout: 3e3 });
297318
+ execSync48("clip", { input: cmd, timeout: 3e3 });
296820
297319
  copied = true;
296821
297320
  } else {
296822
297321
  for (const tool of ["xclip -selection clipboard", "xsel --clipboard --input", "wl-copy"]) {
296823
297322
  try {
296824
- execSync46(tool, { input: cmd, timeout: 3e3, stdio: ["pipe", "pipe", "pipe"] });
297323
+ execSync48(tool, { input: cmd, timeout: 3e3, stdio: ["pipe", "pipe", "pipe"] });
296825
297324
  copied = true;
296826
297325
  break;
296827
297326
  } catch {
@@ -296916,7 +297415,7 @@ var init_commands = __esm({
296916
297415
  // packages/cli/src/tui/project-context.ts
296917
297416
  import { existsSync as existsSync54, readFileSync as readFileSync42, readdirSync as readdirSync15 } from "node:fs";
296918
297417
  import { join as join70, basename as basename13 } from "node:path";
296919
- import { execSync as execSync41 } from "node:child_process";
297418
+ import { execSync as execSync43 } from "node:child_process";
296920
297419
  import { homedir as homedir22, platform as platform5, release } from "node:os";
296921
297420
  function getModelTier(modelName) {
296922
297421
  const m2 = modelName.toLowerCase();
@@ -296958,18 +297457,18 @@ function loadProjectMap(repoRoot) {
296958
297457
  }
296959
297458
  function getGitInfo(repoRoot) {
296960
297459
  try {
296961
- execSync41("git rev-parse --is-inside-work-tree", { cwd: repoRoot, stdio: "pipe" });
297460
+ execSync43("git rev-parse --is-inside-work-tree", { cwd: repoRoot, stdio: "pipe" });
296962
297461
  } catch {
296963
297462
  return "";
296964
297463
  }
296965
297464
  const lines = [];
296966
297465
  try {
296967
- const branch = execSync41("git branch --show-current", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
297466
+ const branch = execSync43("git branch --show-current", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
296968
297467
  if (branch) lines.push(`Branch: ${branch}`);
296969
297468
  } catch {
296970
297469
  }
296971
297470
  try {
296972
- const status = execSync41("git status --porcelain", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
297471
+ const status = execSync43("git status --porcelain", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
296973
297472
  if (status) {
296974
297473
  const changed = status.split("\n").length;
296975
297474
  lines.push(`Working tree: ${changed} changed file(s)`);
@@ -296979,7 +297478,7 @@ function getGitInfo(repoRoot) {
296979
297478
  } catch {
296980
297479
  }
296981
297480
  try {
296982
- const log22 = execSync41("git log --oneline -5 --no-decorate", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
297481
+ const log22 = execSync43("git log --oneline -5 --no-decorate", { cwd: repoRoot, encoding: "utf-8", stdio: "pipe" }).trim();
296983
297482
  if (log22) lines.push(`Recent commits:
296984
297483
  ${log22}`);
296985
297484
  } catch {
@@ -299643,7 +300142,7 @@ var init_promptLoader3 = __esm({
299643
300142
  // packages/cli/src/tui/dream-engine.ts
299644
300143
  import { mkdirSync as mkdirSync29, writeFileSync as writeFileSync29, readFileSync as readFileSync46, existsSync as existsSync58, readdirSync as readdirSync17 } from "node:fs";
299645
300144
  import { join as join75, basename as basename15 } from "node:path";
299646
- import { execSync as execSync42 } from "node:child_process";
300145
+ import { execSync as execSync44 } from "node:child_process";
299647
300146
  function setDreamWriteContent(fn) {
299648
300147
  _dreamWriteContent = fn;
299649
300148
  }
@@ -300017,7 +300516,7 @@ var init_dream_engine = __esm({
300017
300516
  }
300018
300517
  }
300019
300518
  try {
300020
- const output = execSync42(cmd, {
300519
+ const output = execSync44(cmd, {
300021
300520
  cwd: this.repoRoot,
300022
300521
  timeout: 3e4,
300023
300522
  encoding: "utf-8",
@@ -300876,17 +301375,17 @@ ${summaryResult}
300876
301375
  try {
300877
301376
  mkdirSync29(checkpointDir, { recursive: true });
300878
301377
  try {
300879
- const gitStatus = execSync42("git status --porcelain", {
301378
+ const gitStatus = execSync44("git status --porcelain", {
300880
301379
  cwd: this.repoRoot,
300881
301380
  encoding: "utf-8",
300882
301381
  timeout: 1e4
300883
301382
  });
300884
- const gitDiff = execSync42("git diff", {
301383
+ const gitDiff = execSync44("git diff", {
300885
301384
  cwd: this.repoRoot,
300886
301385
  encoding: "utf-8",
300887
301386
  timeout: 1e4
300888
301387
  });
300889
- const gitHash = execSync42("git rev-parse HEAD 2>/dev/null || echo 'no-git'", {
301388
+ const gitHash = execSync44("git rev-parse HEAD 2>/dev/null || echo 'no-git'", {
300890
301389
  cwd: this.repoRoot,
300891
301390
  encoding: "utf-8",
300892
301391
  timeout: 5e3
@@ -306479,7 +306978,7 @@ var init_profiles = __esm({
306479
306978
  });
306480
306979
 
306481
306980
  // packages/cli/src/docker.ts
306482
- import { execSync as execSync43, spawn as spawn23 } from "node:child_process";
306981
+ import { execSync as execSync45, spawn as spawn23 } from "node:child_process";
306483
306982
  import { existsSync as existsSync66, mkdirSync as mkdirSync35, writeFileSync as writeFileSync33 } from "node:fs";
306484
306983
  import { join as join83, resolve as resolve33, dirname as dirname24 } from "node:path";
306485
306984
  import { homedir as homedir24 } from "node:os";
@@ -306500,7 +306999,7 @@ function getDockerDir() {
306500
306999
  }
306501
307000
  function isDockerAvailable() {
306502
307001
  try {
306503
- execSync43("docker info", { stdio: "pipe", timeout: 1e4 });
307002
+ execSync45("docker info", { stdio: "pipe", timeout: 1e4 });
306504
307003
  return true;
306505
307004
  } catch {
306506
307005
  return false;
@@ -306508,7 +307007,7 @@ function isDockerAvailable() {
306508
307007
  }
306509
307008
  function isDockerInstalled() {
306510
307009
  try {
306511
- execSync43("docker --version", { stdio: "pipe", timeout: 5e3 });
307010
+ execSync45("docker --version", { stdio: "pipe", timeout: 5e3 });
306512
307011
  return true;
306513
307012
  } catch {
306514
307013
  return false;
@@ -306533,31 +307032,31 @@ async function ensureDocker() {
306533
307032
  }
306534
307033
  try {
306535
307034
  console.log("[oa-docker] Docker not found. Installing via get.docker.com...");
306536
- execSync43("curl -fsSL https://get.docker.com | sh", {
307035
+ execSync45("curl -fsSL https://get.docker.com | sh", {
306537
307036
  stdio: "inherit",
306538
307037
  timeout: 3e5
306539
307038
  });
306540
307039
  const user = process.env["USER"] || process.env["LOGNAME"];
306541
307040
  if (user) {
306542
307041
  try {
306543
- execSync43(`sudo usermod -aG docker ${user}`, { stdio: "pipe" });
307042
+ execSync45(`sudo usermod -aG docker ${user}`, { stdio: "pipe" });
306544
307043
  } catch {
306545
307044
  }
306546
307045
  }
306547
307046
  try {
306548
- execSync43("sudo systemctl start docker", { stdio: "pipe", timeout: 15e3 });
307047
+ execSync45("sudo systemctl start docker", { stdio: "pipe", timeout: 15e3 });
306549
307048
  } catch {
306550
307049
  }
306551
307050
  try {
306552
- execSync43("nvidia-smi", { stdio: "pipe", timeout: 5e3 });
306553
- const runtimes = execSync43("docker info --format '{{json .Runtimes}}'", {
307051
+ execSync45("nvidia-smi", { stdio: "pipe", timeout: 5e3 });
307052
+ const runtimes = execSync45("docker info --format '{{json .Runtimes}}'", {
306554
307053
  stdio: "pipe",
306555
307054
  timeout: 5e3
306556
307055
  }).toString();
306557
307056
  if (!runtimes.includes("nvidia")) {
306558
307057
  console.log("[oa-docker] NVIDIA GPU detected. Installing nvidia-container-toolkit...");
306559
307058
  try {
306560
- execSync43(`
307059
+ execSync45(`
306561
307060
  curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg 2>/dev/null
306562
307061
  curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list > /dev/null 2>&1
306563
307062
  sudo apt-get update -qq 2>/dev/null && sudo apt-get install -y -qq nvidia-container-toolkit 2>/dev/null || ( sudo dnf install -y nvidia-container-toolkit 2>/dev/null || sudo yum install -y nvidia-container-toolkit 2>/dev/null || true )
@@ -306587,7 +307086,7 @@ async function ensureDocker() {
306587
307086
  }
306588
307087
  async function ensureNvidiaToolkit() {
306589
307088
  try {
306590
- execSync43("nvidia-smi --query-gpu=name --format=csv,noheader", { stdio: "pipe", timeout: 5e3 });
307089
+ execSync45("nvidia-smi --query-gpu=name --format=csv,noheader", { stdio: "pipe", timeout: 5e3 });
306591
307090
  } catch {
306592
307091
  return { ok: false, message: "No NVIDIA GPU detected (nvidia-smi not found)" };
306593
307092
  }
@@ -306598,7 +307097,7 @@ async function ensureNvidiaToolkit() {
306598
307097
  return { ok: false, message: "Auto-install only supported on Linux. Install manually: https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/install-guide.html" };
306599
307098
  }
306600
307099
  try {
306601
- execSync43(`
307100
+ execSync45(`
306602
307101
  curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg 2>/dev/null
306603
307102
  curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list > /dev/null 2>&1
306604
307103
  sudo apt-get update -qq 2>/dev/null && sudo apt-get install -y -qq nvidia-container-toolkit 2>/dev/null || ( sudo dnf install -y nvidia-container-toolkit 2>/dev/null || sudo yum install -y nvidia-container-toolkit 2>/dev/null || true )
@@ -306612,7 +307111,7 @@ async function ensureNvidiaToolkit() {
306612
307111
  }
306613
307112
  function isOaImageBuilt() {
306614
307113
  try {
306615
- const out = execSync43(`docker images -q ${OA_IMAGE}:${OA_IMAGE_TAG}`, {
307114
+ const out = execSync45(`docker images -q ${OA_IMAGE}:${OA_IMAGE_TAG}`, {
306616
307115
  stdio: "pipe",
306617
307116
  timeout: 5e3
306618
307117
  }).toString().trim();
@@ -306636,7 +307135,7 @@ async function ensureOaImage(force = false) {
306636
307135
  }
306637
307136
  try {
306638
307137
  console.log(`[oa-docker] Building image ${OA_IMAGE}:${OA_IMAGE_TAG}...`);
306639
- execSync43(`docker build -t ${OA_IMAGE}:${OA_IMAGE_TAG} ${buildContext}`, {
307138
+ execSync45(`docker build -t ${OA_IMAGE}:${OA_IMAGE_TAG} ${buildContext}`, {
306640
307139
  stdio: "inherit",
306641
307140
  timeout: 6e5
306642
307141
  // 10 min
@@ -306710,11 +307209,11 @@ exec "$@"
306710
307209
  }
306711
307210
  function hasNvidiaGpu() {
306712
307211
  try {
306713
- execSync43("nvidia-smi --query-gpu=name --format=csv,noheader", {
307212
+ execSync45("nvidia-smi --query-gpu=name --format=csv,noheader", {
306714
307213
  stdio: "pipe",
306715
307214
  timeout: 5e3
306716
307215
  });
306717
- const runtimes = execSync43("docker info --format '{{json .Runtimes}}'", {
307216
+ const runtimes = execSync45("docker info --format '{{json .Runtimes}}'", {
306718
307217
  stdio: "pipe",
306719
307218
  timeout: 5e3
306720
307219
  }).toString();
@@ -306784,7 +307283,7 @@ import * as https3 from "node:https";
306784
307283
  import { createRequire as createRequire4 } from "node:module";
306785
307284
  import { fileURLToPath as fileURLToPath16 } from "node:url";
306786
307285
  import { dirname as dirname25, join as join84, resolve as resolve34 } from "node:path";
306787
- import { spawn as spawn24, execSync as execSync44 } from "node:child_process";
307286
+ import { spawn as spawn24, execSync as execSync46 } from "node:child_process";
306788
307287
  import { mkdirSync as mkdirSync36, writeFileSync as writeFileSync34, readFileSync as readFileSync53, readdirSync as readdirSync23, existsSync as existsSync67 } from "node:fs";
306789
307288
  import { randomBytes as randomBytes19, randomUUID as randomUUID5 } from "node:crypto";
306790
307289
  function getVersion3() {
@@ -307792,7 +308291,7 @@ function handleV1RunsDelete(res, id) {
307792
308291
  const containerName = `oa-${id}`;
307793
308292
  if (job.sandbox === "container") {
307794
308293
  try {
307795
- execSync44(`docker stop ${containerName}`, { timeout: 5e3, stdio: "ignore" });
308294
+ execSync46(`docker stop ${containerName}`, { timeout: 5e3, stdio: "ignore" });
307796
308295
  } catch {
307797
308296
  }
307798
308297
  }
@@ -308702,7 +309201,7 @@ import { createRequire as createRequire5 } from "node:module";
308702
309201
  import { fileURLToPath as fileURLToPath17 } from "node:url";
308703
309202
  import { readFileSync as readFileSync54, writeFileSync as writeFileSync35, appendFileSync as appendFileSync6, rmSync as rmSync4, readdirSync as readdirSync24, mkdirSync as mkdirSync37 } from "node:fs";
308704
309203
  import { existsSync as existsSync68 } from "node:fs";
308705
- import { execSync as execSync45 } from "node:child_process";
309204
+ import { execSync as execSync47 } from "node:child_process";
308706
309205
  import { homedir as homedir25 } from "node:os";
308707
309206
  function formatTimeAgo(date) {
308708
309207
  const seconds = Math.floor((Date.now() - date.getTime()) / 1e3);
@@ -308869,6 +309368,8 @@ function buildTools(repoRoot, config, contextWindowSize, modelTier) {
308869
309368
  new CameraCaptureTool(),
308870
309369
  new AudioCaptureTool(),
308871
309370
  new AudioPlaybackTool(),
309371
+ new WifiControlTool(),
309372
+ new BluetoothScanTool(),
308872
309373
  // Full OA sub-process — callbacks wired after runner + statusBar created
308873
309374
  (() => {
308874
309375
  _fullSubAgentToolRef = new FullSubAgentTool(repoRoot, config.model, config.backendUrl);
@@ -313027,7 +313528,7 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
313027
313528
  try {
313028
313529
  if (process.platform === "win32") {
313029
313530
  try {
313030
- execSync45(`taskkill /F /PID ${pid}`, { timeout: 5e3, stdio: "ignore" });
313531
+ execSync47(`taskkill /F /PID ${pid}`, { timeout: 5e3, stdio: "ignore" });
313031
313532
  } catch {
313032
313533
  }
313033
313534
  } else {
@@ -313054,7 +313555,7 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
313054
313555
  if (pid > 0) {
313055
313556
  if (process.platform === "win32") {
313056
313557
  try {
313057
- execSync45(`taskkill /F /PID ${pid}`, { timeout: 5e3, stdio: "ignore" });
313558
+ execSync47(`taskkill /F /PID ${pid}`, { timeout: 5e3, stdio: "ignore" });
313058
313559
  } catch {
313059
313560
  }
313060
313561
  } else {
@@ -313071,7 +313572,7 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
313071
313572
  } catch {
313072
313573
  }
313073
313574
  try {
313074
- execSync45(process.platform === "win32" ? "timeout /t 1 /nobreak >nul" : "sleep 0.5", { timeout: 3e3, stdio: "ignore" });
313575
+ execSync47(process.platform === "win32" ? "timeout /t 1 /nobreak >nul" : "sleep 0.5", { timeout: 3e3, stdio: "ignore" });
313075
313576
  } catch {
313076
313577
  }
313077
313578
  const oaPath = join85(repoRoot, OA_DIR);
@@ -313085,14 +313586,14 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
313085
313586
  } catch (err) {
313086
313587
  if (attempt < 2) {
313087
313588
  try {
313088
- execSync45(process.platform === "win32" ? "timeout /t 1 /nobreak >nul" : "sleep 0.3", { timeout: 3e3, stdio: "ignore" });
313589
+ execSync47(process.platform === "win32" ? "timeout /t 1 /nobreak >nul" : "sleep 0.3", { timeout: 3e3, stdio: "ignore" });
313089
313590
  } catch {
313090
313591
  }
313091
313592
  } else {
313092
313593
  writeContent(() => renderWarning(`Could not fully remove ${OA_DIR}/: ${err instanceof Error ? err.message : String(err)}`));
313093
313594
  if (process.platform === "win32") {
313094
313595
  try {
313095
- execSync45(`rd /s /q "${oaPath}"`, { timeout: 1e4, stdio: "ignore" });
313596
+ execSync47(`rd /s /q "${oaPath}"`, { timeout: 1e4, stdio: "ignore" });
313096
313597
  deleted = true;
313097
313598
  } catch {
313098
313599
  }