@pulso/companion 0.2.0 → 0.2.2

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 +41 -4
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -195,6 +195,9 @@ async function spotifySearch(query) {
195
195
  } catch {
196
196
  }
197
197
  let trackIds = await searchBraveForSpotifyTracks(query);
198
+ if (trackIds.length === 0) {
199
+ trackIds = await searchDDGForSpotifyTracks(query);
200
+ }
198
201
  if (trackIds.length === 0) {
199
202
  trackIds = await searchStartpageForSpotifyTracks(query);
200
203
  }
@@ -232,6 +235,28 @@ async function searchBraveForSpotifyTracks(query) {
232
235
  return [];
233
236
  }
234
237
  }
238
+ async function searchDDGForSpotifyTracks(query) {
239
+ try {
240
+ const searchQuery = `spotify track ${query} site:open.spotify.com`;
241
+ const url = `https://html.duckduckgo.com/html/?q=${encodeURIComponent(searchQuery)}`;
242
+ const controller = new AbortController();
243
+ const timeout = setTimeout(() => controller.abort(), 8e3);
244
+ const res = await fetch(url, {
245
+ headers: { "User-Agent": UA, Accept: "text/html" },
246
+ signal: controller.signal
247
+ });
248
+ clearTimeout(timeout);
249
+ if (!res.ok) return [];
250
+ const html = await res.text();
251
+ const trackIds = /* @__PURE__ */ new Set();
252
+ for (const m of html.matchAll(/open\.spotify\.com(?:\/intl-[a-z]+)?\/track\/([a-zA-Z0-9]{22})/g)) {
253
+ trackIds.add(m[1]);
254
+ }
255
+ return [...trackIds];
256
+ } catch {
257
+ return [];
258
+ }
259
+ }
235
260
  async function searchStartpageForSpotifyTracks(query) {
236
261
  try {
237
262
  const searchQuery = `${query} spotify open.spotify.com`;
@@ -1315,11 +1340,13 @@ var ws = null;
1315
1340
  var reconnectTimer = null;
1316
1341
  var heartbeatTimer = null;
1317
1342
  var HEARTBEAT_INTERVAL = 3e4;
1343
+ var reconnectAttempts = 0;
1318
1344
  function connect() {
1319
1345
  console.log("\u{1F50C} Connecting to Pulso...");
1320
1346
  console.log(` ${WS_URL.replace(/token=.*/, "token=***")}`);
1321
1347
  ws = new WebSocket(WS_URL);
1322
1348
  ws.on("open", () => {
1349
+ reconnectAttempts = 0;
1323
1350
  console.log("\u2705 Connected to Pulso!");
1324
1351
  console.log(`\u{1F5A5}\uFE0F Companion is active \u2014 ${ACCESS_LEVEL === "full" ? "full device access" : "sandboxed mode"}`);
1325
1352
  console.log("");
@@ -1370,12 +1397,20 @@ function connect() {
1370
1397
  }
1371
1398
  });
1372
1399
  ws.on("close", (code, reason) => {
1400
+ const reasonStr = reason.toString() || "unknown";
1373
1401
  console.log(`
1374
- \u{1F50C} Disconnected (${code}: ${reason.toString() || "unknown"})`);
1402
+ \u{1F50C} Disconnected (${code}: ${reasonStr})`);
1375
1403
  if (heartbeatTimer) {
1376
1404
  clearInterval(heartbeatTimer);
1377
1405
  heartbeatTimer = null;
1378
1406
  }
1407
+ if (reasonStr === "New connection from same user") {
1408
+ console.log("\n\u26A0\uFE0F Another Pulso Companion instance is already connected.");
1409
+ console.log(" This instance will exit. Only one companion per account is supported.");
1410
+ console.log(" If this is unexpected, close other terminals running Pulso Companion.\n");
1411
+ process.exit(0);
1412
+ return;
1413
+ }
1379
1414
  scheduleReconnect();
1380
1415
  });
1381
1416
  ws.on("error", (err) => {
@@ -1384,15 +1419,17 @@ function connect() {
1384
1419
  }
1385
1420
  function scheduleReconnect() {
1386
1421
  if (reconnectTimer) return;
1387
- console.log(` Reconnecting in ${RECONNECT_DELAY / 1e3}s...`);
1422
+ reconnectAttempts++;
1423
+ const delay = Math.min(RECONNECT_DELAY * Math.pow(2, reconnectAttempts - 1), 6e4);
1424
+ console.log(` Reconnecting in ${(delay / 1e3).toFixed(0)}s... (attempt ${reconnectAttempts})`);
1388
1425
  reconnectTimer = setTimeout(() => {
1389
1426
  reconnectTimer = null;
1390
1427
  connect();
1391
- }, RECONNECT_DELAY);
1428
+ }, delay);
1392
1429
  }
1393
1430
  console.log("");
1394
1431
  console.log(" \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557");
1395
- console.log(" \u2551 \u{1FAC0} Pulso Mac Companion v0.1.9 \u2551");
1432
+ console.log(" \u2551 \u{1FAC0} Pulso Mac Companion v0.2.2 \u2551");
1396
1433
  console.log(" \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D");
1397
1434
  console.log("");
1398
1435
  setupPermissions().then(() => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pulso/companion",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "type": "module",
5
5
  "description": "Pulso Companion — gives your AI agent real control over your computer",
6
6
  "bin": {