agentic-relay 5.0.8 → 5.0.9

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/bin/install.mjs +106 -1
  2. package/package.json +1 -1
package/bin/install.mjs CHANGED
@@ -36,6 +36,7 @@ import { fileURLToPath } from "url";
36
36
  import { createInterface } from "readline/promises";
37
37
  import { stdin, stdout } from "process";
38
38
  import { execSync } from "child_process";
39
+ import { randomBytes, createHash } from "crypto";
39
40
  import { parseInstallArgs } from "./lib/install-args.mjs";
40
41
  import {
41
42
  npmGlobalPrefix,
@@ -63,6 +64,8 @@ const SIGNUP_URL = "https://attentionmarket-auth.vercel.app";
63
64
  const API_BASE =
64
65
  "https://peruwnbrqkvmrldhpoom.supabase.co/functions/v1/api-v1";
65
66
  const MCP_URL = "https://peruwnbrqkvmrldhpoom.supabase.co/functions/v1/mcp";
67
+ const CLI_AUTH_URL =
68
+ "https://peruwnbrqkvmrldhpoom.supabase.co/functions/v1/cli-auth";
66
69
  const SERVER_NAME = "agent-relay";
67
70
 
68
71
  // ═══════════════════════════════════════════════════════════════════════
@@ -728,6 +731,94 @@ function linkGlobalCli() {
728
731
  return "failed";
729
732
  }
730
733
 
734
+ const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
735
+
736
+ // Open a URL in the user's default browser (best-effort, per platform).
737
+ function openBrowser(url) {
738
+ const cmd =
739
+ process.platform === "darwin"
740
+ ? "open"
741
+ : process.platform === "win32"
742
+ ? "start \"\""
743
+ : "xdg-open";
744
+ try {
745
+ execSync(`${cmd} "${url}"`, { stdio: "ignore" });
746
+ return true;
747
+ } catch {
748
+ return false;
749
+ }
750
+ }
751
+
752
+ /**
753
+ * Browser sign-in via the `cli-auth` device-authorization flow: open a page,
754
+ * the user verifies their phone (which mints their key), and we poll until the
755
+ * key is released to us. PKCE (the verifier stays on this machine) is what makes
756
+ * the released key safe. Returns an am_live_ key, or null if it didn't complete.
757
+ */
758
+ async function browserAuth() {
759
+ const codeVerifier = randomBytes(32).toString("hex");
760
+ const codeChallenge = createHash("sha256").update(codeVerifier).digest("hex");
761
+
762
+ let start;
763
+ try {
764
+ const r = await fetch(CLI_AUTH_URL, {
765
+ method: "POST",
766
+ headers: { "Content-Type": "application/json" },
767
+ body: JSON.stringify({ action: "start", code_challenge: codeChallenge }),
768
+ });
769
+ start = await r.json().catch(() => ({}));
770
+ if (!r.ok || !start.session_id) {
771
+ throw new Error(start.error || `HTTP ${r.status}`);
772
+ }
773
+ } catch (err) {
774
+ warn(`Couldn't start browser sign-in (${err.message}).`);
775
+ return null;
776
+ }
777
+
778
+ const {
779
+ session_id,
780
+ user_code,
781
+ authorize_url,
782
+ interval = 3,
783
+ expires_in = 600,
784
+ } = start;
785
+
786
+ console.log("");
787
+ log("Opening your browser to authorize…");
788
+ const opened = openBrowser(authorize_url);
789
+ console.log("");
790
+ console.log(opened ? " If it didn't open, visit:" : " Open this link to authorize:");
791
+ console.log(` \x1b[4m${authorize_url}\x1b[0m`);
792
+ if (user_code) console.log(` Verification code: \x1b[1m${user_code}\x1b[0m`);
793
+ console.log("");
794
+ log("Waiting for you to finish in the browser…");
795
+
796
+ const deadline = Date.now() + expires_in * 1000;
797
+ while (Date.now() < deadline) {
798
+ await sleep(interval * 1000);
799
+ try {
800
+ const r = await fetch(CLI_AUTH_URL, {
801
+ method: "POST",
802
+ headers: { "Content-Type": "application/json" },
803
+ body: JSON.stringify({ action: "poll", session_id, code_verifier: codeVerifier }),
804
+ });
805
+ const data = await r.json().catch(() => ({}));
806
+ if (r.ok && data.status === "authorized" && data.api_key_live) {
807
+ return data.api_key_live;
808
+ }
809
+ if (r.status === 410 || data.status === "expired") {
810
+ warn("That sign-in link expired. Let's try again.");
811
+ return null;
812
+ }
813
+ // status "pending" → keep polling
814
+ } catch {
815
+ // transient network blip — keep polling until the deadline
816
+ }
817
+ }
818
+ warn("Timed out waiting for browser authorization.");
819
+ return null;
820
+ }
821
+
731
822
  async function setupApiKeyInteractive() {
732
823
  // Verify-then-refresh: on a reinstall, keep a cached key that still works, but
733
824
  // wipe a stale/revoked one and prompt for a fresh key — so a dead key never
@@ -753,12 +844,26 @@ async function setupApiKeyInteractive() {
753
844
  return false;
754
845
  }
755
846
 
847
+ // Seamless path: browser sign-in — no key to find, type, or paste. Verify
848
+ // your phone in the browser and we pick up the minted key automatically.
849
+ const browserKey = await browserAuth();
850
+ if (browserKey) {
851
+ const check = await verifyKey(browserKey);
852
+ if (check.ok) {
853
+ saveApiKey(browserKey);
854
+ return true;
855
+ }
856
+ warn(`Signed in, but the key didn't verify (${check.detail}).`);
857
+ }
858
+
859
+ // Fallback: paste a key manually (browser couldn't open, timed out, or you
860
+ // already have a key).
756
861
  console.log("");
757
862
  log("API key setup");
758
863
  console.log("");
759
864
  console.log(" Your API key starts with \x1b[1mam_live_\x1b[0m.");
760
865
  console.log(
761
- ` Don't have one? Sign up at \x1b[4m${SIGNUP_URL}\x1b[0m (Account tab).`,
866
+ ` Don't have one? Re-run and choose the browser sign-in, or sign up at \x1b[4m${SIGNUP_URL}\x1b[0m.`,
762
867
  );
763
868
  console.log("");
764
869
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentic-relay",
3
- "version": "5.0.8",
3
+ "version": "5.0.9",
4
4
  "description": "Install Agent Relay across 17+ agents — Claude Code, Codex, Cursor, Gemini CLI, Goose, Windsurf, Cline, BoltAI, Claude Desktop, VS Code, Amazon Q, Roo Code, Witsy, LibreChat, OpenClaw, Tome, Raycast — hire verified expert agents to build with you, plus the `agentrelay` CLI for live specialist sessions and deliverable fetch",
5
5
  "bin": {
6
6
  "agentrelay": "bin/cli.mjs"