zephex 2.1.1 → 2.1.3

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/cli.js +49 -285
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -195,16 +195,13 @@ var require_picocolors = __commonJS((exports, module) => {
195
195
  });
196
196
 
197
197
  // src/cli.ts
198
- import { fileURLToPath as fileURLToPath3 } from "url";
198
+ import { fileURLToPath as fileURLToPath2 } from "url";
199
199
  import { resolve, dirname } from "path";
200
200
 
201
201
  // src/commands/setup.ts
202
- import http from "node:http";
203
- import crypto from "node:crypto";
204
202
  import fs7 from "node:fs";
205
203
  import path3 from "node:path";
206
204
  import os3 from "node:os";
207
- import { fileURLToPath as fileURLToPath2 } from "node:url";
208
205
  import { spawnSync } from "node:child_process";
209
206
 
210
207
  // node_modules/.bun/@clack+prompts@0.9.1/node_modules/@clack/prompts/dist/index.mjs
@@ -1423,38 +1420,10 @@ async function runSkills(argv) {
1423
1420
  }
1424
1421
 
1425
1422
  // src/commands/setup.ts
1426
- var CACHED_CLI_VERSION = null;
1427
- function getCliVersion() {
1428
- if (CACHED_CLI_VERSION !== null)
1429
- return CACHED_CLI_VERSION;
1430
- try {
1431
- const here = fileURLToPath2(import.meta.url);
1432
- let dir = path3.dirname(here);
1433
- for (let depth = 0;depth < 6; depth++) {
1434
- const candidate = path3.join(dir, "package.json");
1435
- if (fs7.existsSync(candidate)) {
1436
- const json = JSON.parse(fs7.readFileSync(candidate, "utf8"));
1437
- if (json.name === "zephex" && typeof json.version === "string") {
1438
- CACHED_CLI_VERSION = json.version;
1439
- return CACHED_CLI_VERSION;
1440
- }
1441
- }
1442
- const parent = path3.dirname(dir);
1443
- if (parent === dir)
1444
- break;
1445
- dir = parent;
1446
- }
1447
- } catch {}
1448
- CACHED_CLI_VERSION = "unknown";
1449
- return CACHED_CLI_VERSION;
1450
- }
1451
- var DEFAULT_AUTH0_CLI_CLIENT_ID = process.env.AUTH0_CLI_CLIENT_ID ?? "AUTH0_CLI_CLIENT_ID_NOT_SET";
1452
- var DEFAULT_AUTH0_DOMAIN = "zephex.us.auth0.com";
1453
- var DEFAULT_AUTH0_AUDIENCE = "https://zephex.dev/mcp";
1423
+ var DEFAULT_AUTH0_CLI_CLIENT_ID = process.env.AUTH0_CLI_CLIENT_ID ?? "2JrCMEKyOdY1YDZxInqTamSGNSCX9DaS";
1454
1424
  var ZEPHEX_API_BASE = "https://zephex.dev";
1455
1425
  var ZEPHEX_MCP_URL = "https://zephex.dev/mcp";
1456
1426
  var DASHBOARD_KEYS_URL = "https://zephex.dev/dashboard/keys";
1457
- var CALLBACK_PORTS = [52748, 52749, 52750];
1458
1427
  function parseFlags2(argv) {
1459
1428
  let mode = null;
1460
1429
  let editor = null;
@@ -1577,257 +1546,55 @@ function prettyPath2(absPath) {
1577
1546
  }
1578
1547
  return absPath;
1579
1548
  }
1580
- function base64url(buf) {
1581
- return buf.toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
1582
- }
1583
- function base64urlDecode(input) {
1584
- const pad = input.length % 4 === 0 ? "" : "=".repeat(4 - input.length % 4);
1585
- const normalized = input.replace(/-/g, "+").replace(/_/g, "/") + pad;
1586
- return Buffer.from(normalized, "base64");
1587
- }
1588
- function generatePkce() {
1589
- const verifier = base64url(crypto.randomBytes(32));
1590
- const challenge = base64url(crypto.createHash("sha256").update(verifier).digest());
1591
- return { verifier, challenge };
1592
- }
1593
- function decodeJwtEmail(token) {
1594
- try {
1595
- const parts = token.split(".");
1596
- if (parts.length < 2)
1597
- return null;
1598
- const payloadStr = base64urlDecode(parts[1] ?? "").toString("utf8");
1599
- const payload = JSON.parse(payloadStr);
1600
- const email = payload["email"];
1601
- if (typeof email === "string" && email.length > 0)
1602
- return email;
1603
- return null;
1604
- } catch {
1605
- return null;
1606
- }
1607
- }
1608
- var SUCCESS_HTML = `<!DOCTYPE html>
1609
- <html>
1610
- <head>
1611
- <title>Zephex Connected</title>
1612
- <style>
1613
- body { background: #0f0f13; color: #e0e0e0; font-family: ui-sans-serif, system-ui, sans-serif;
1614
- display: flex; align-items: center; justify-content: center; height: 100vh; margin: 0; }
1615
- .box { text-align: center; }
1616
- .check { font-size: 48px; color: #7c3aed; margin-bottom: 16px; }
1617
- h1 { font-size: 24px; margin: 0 0 8px; }
1618
- p { color: #888; margin: 0; }
1619
- </style>
1620
- </head>
1621
- <body>
1622
- <div class="box">
1623
- <div class="check">✓</div>
1624
- <h1>You're connected to Zephex</h1>
1625
- <p>You can close this tab and return to your terminal.</p>
1626
- </div>
1627
- </body>
1628
- </html>`;
1629
- function errorHtml(message) {
1630
- return `<!DOCTYPE html>
1631
- <html>
1632
- <head>
1633
- <title>Zephex — Login failed</title>
1634
- <style>
1635
- body { background: #0f0f13; color: #e0e0e0; font-family: ui-sans-serif, system-ui, sans-serif;
1636
- display: flex; align-items: center; justify-content: center; height: 100vh; margin: 0; }
1637
- .box { text-align: center; max-width: 480px; padding: 0 24px; }
1638
- .x { font-size: 48px; color: #dc2626; margin-bottom: 16px; }
1639
- h1 { font-size: 24px; margin: 0 0 8px; }
1640
- p { color: #888; margin: 0; }
1641
- </style>
1642
- </head>
1643
- <body>
1644
- <div class="box">
1645
- <div class="x">✕</div>
1646
- <h1>Login failed</h1>
1647
- <p>${escapeHtml(message)}</p>
1648
- </div>
1649
- </body>
1650
- </html>`;
1651
- }
1652
- async function startCallbackServer(expectedState) {
1653
- let lastErr = null;
1654
- for (const port of CALLBACK_PORTS) {
1655
- try {
1656
- const server = http.createServer();
1657
- await new Promise((resolve, reject) => {
1658
- const onError = (err) => {
1659
- server.removeListener("listening", onListen);
1660
- reject(err);
1661
- };
1662
- const onListen = () => {
1663
- server.removeListener("error", onError);
1664
- resolve();
1665
- };
1666
- server.once("error", onError);
1667
- server.once("listening", onListen);
1668
- server.listen(port, "127.0.0.1");
1669
- });
1670
- const result = new Promise((resolve, reject) => {
1671
- server.on("request", (req, res) => {
1672
- if (!req.url) {
1673
- res.writeHead(400).end();
1674
- return;
1675
- }
1676
- const reqUrl = new URL(req.url, `http://127.0.0.1:${port}`);
1677
- if (reqUrl.pathname !== "/callback") {
1678
- res.writeHead(404, { "Content-Type": "text/plain" }).end("Not found");
1679
- return;
1680
- }
1681
- const code = reqUrl.searchParams.get("code");
1682
- const state = reqUrl.searchParams.get("state");
1683
- const errParam = reqUrl.searchParams.get("error");
1684
- const errDesc = reqUrl.searchParams.get("error_description");
1685
- if (errParam) {
1686
- res.writeHead(400, { "Content-Type": "text/html; charset=utf-8" }).end(errorHtml(errDesc ?? errParam));
1687
- reject(new Error(`Auth0 returned error: ${errParam}${errDesc ? ` (${errDesc})` : ""}`));
1688
- return;
1689
- }
1690
- if (!code || !state) {
1691
- res.writeHead(400, { "Content-Type": "text/html; charset=utf-8" }).end(errorHtml("Missing authorization code or state."));
1692
- reject(new Error("Missing code or state on callback"));
1693
- return;
1694
- }
1695
- if (state !== expectedState) {
1696
- res.writeHead(400, { "Content-Type": "text/html; charset=utf-8" }).end(errorHtml("Invalid state — possible CSRF."));
1697
- reject(new Error("OAuth state mismatch — possible CSRF; aborting"));
1698
- return;
1699
- }
1700
- res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" }).end(SUCCESS_HTML);
1701
- resolve({ code, state });
1702
- });
1703
- });
1704
- return {
1705
- port,
1706
- waitForCallback: () => result,
1707
- close: () => {
1708
- server.close();
1709
- }
1710
- };
1711
- } catch (err) {
1712
- const e2 = err;
1713
- lastErr = e2 instanceof Error ? e2 : new Error(String(e2));
1714
- if (e2?.code !== "EADDRINUSE") {
1715
- throw lastErr;
1716
- }
1717
- }
1718
- }
1719
- throw new Error(`Could not bind any local callback port (${CALLBACK_PORTS.join(", ")}). ${lastErr?.message ?? ""}`.trim());
1720
- }
1721
- function escapeHtml(value) {
1722
- return value.replace(/[&<>"']/g, (ch) => {
1723
- switch (ch) {
1724
- case "&":
1725
- return "&amp;";
1726
- case "<":
1727
- return "&lt;";
1728
- case ">":
1729
- return "&gt;";
1730
- case '"':
1731
- return "&quot;";
1732
- case "'":
1733
- return "&#39;";
1734
- default:
1735
- return ch;
1736
- }
1737
- });
1738
- }
1739
- async function exchangeCodeForToken(params) {
1740
- const resp = await fetch(`https://${params.domain}/oauth/token`, {
1549
+ async function loginAndGetApiKey(editor) {
1550
+ const sessionResp = await fetch(`${ZEPHEX_API_BASE}/api/cli/session`, {
1741
1551
  method: "POST",
1742
- headers: { "Content-Type": "application/json" },
1743
- body: JSON.stringify({
1744
- grant_type: "authorization_code",
1745
- client_id: params.clientId,
1746
- code_verifier: params.verifier,
1747
- code: params.code,
1748
- redirect_uri: params.redirectUri
1749
- })
1552
+ headers: { "Content-Type": "application/json" }
1750
1553
  });
1751
- if (!resp.ok) {
1752
- const text = await resp.text().catch(() => "");
1753
- throw new Error(`Token exchange failed (${resp.status}): ${text || resp.statusText}`);
1754
- }
1755
- const json = await resp.json();
1756
- if (!json.access_token || typeof json.access_token !== "string") {
1757
- throw new Error("Token response missing access_token");
1554
+ if (!sessionResp.ok) {
1555
+ throw new Error("Failed to start auth session. Is zephex.dev reachable?");
1758
1556
  }
1759
- return json;
1760
- }
1761
- async function loginAndGetApiKey(editor) {
1762
- const clientId = process.env["AUTH0_CLI_CLIENT_ID"] || DEFAULT_AUTH0_CLI_CLIENT_ID;
1763
- const domain = process.env["AUTH0_DOMAIN"] || DEFAULT_AUTH0_DOMAIN;
1764
- const audience = process.env["AUTH0_AUDIENCE"] || DEFAULT_AUTH0_AUDIENCE;
1765
- const { verifier, challenge } = generatePkce();
1766
- const state = base64url(crypto.randomBytes(16));
1767
- const callback = await startCallbackServer(state);
1557
+ const { session_id } = await sessionResp.json();
1558
+ const authUrl = `${ZEPHEX_API_BASE}/cli/auth?session=${encodeURIComponent(session_id)}`;
1559
+ ye("Opening zephex.dev in your browser...", "Sign in");
1768
1560
  try {
1769
- const redirectUri = `http://127.0.0.1:${callback.port}/callback`;
1770
- const authorizeUrl = `https://${domain}/authorize` + `?response_type=code` + `&client_id=${encodeURIComponent(clientId)}` + `&redirect_uri=${encodeURIComponent(redirectUri)}` + `&scope=${encodeURIComponent("openid profile email")}` + `&state=${encodeURIComponent(state)}` + `&code_challenge=${encodeURIComponent(challenge)}` + `&code_challenge_method=S256` + `&audience=${encodeURIComponent(audience)}`;
1771
- ye("Opening zephex.dev in your browser...", "Sign in");
1772
- try {
1773
- await open_default(authorizeUrl);
1774
- } catch {
1775
- v2.message(`If your browser didn't open, paste this URL:
1776
- ${authorizeUrl}`);
1777
- }
1778
- const sp = L2();
1779
- sp.start("Waiting for you to sign in...");
1780
- try {
1781
- const { code } = await callback.waitForCallback();
1782
- sp.message("Waiting for you to sign in...");
1783
- const token = await exchangeCodeForToken({
1784
- domain,
1785
- clientId,
1786
- code,
1787
- verifier,
1788
- redirectUri
1789
- });
1790
- const email = decodeJwtEmail(token.id_token ?? "") ?? decodeJwtEmail(token.access_token);
1791
- const keyInfo = await provisionCliKey(token.access_token, editor);
1792
- sp.stop("Signed in");
1793
- return { keyInfo, email };
1794
- } catch (err) {
1795
- sp.stop("Sign-in failed");
1796
- throw err;
1797
- }
1798
- } finally {
1799
- callback.close();
1800
- }
1801
- }
1802
- async function provisionCliKey(accessToken, editor) {
1803
- const cliVersion = getCliVersion();
1804
- const resp = await fetch(`${ZEPHEX_API_BASE}/api/cli/create-key`, {
1805
- method: "POST",
1806
- headers: {
1807
- "Content-Type": "application/json",
1808
- Authorization: `Bearer ${accessToken}`,
1809
- "X-Zephex-CLI-Version": cliVersion,
1810
- "X-Zephex-Editor": editor,
1811
- "User-Agent": `zephex-cli/${cliVersion} (${process.platform}; node-${process.versions.node})`
1812
- },
1813
- body: JSON.stringify({ editor })
1814
- });
1815
- if (!resp.ok) {
1816
- let detail = "";
1817
- try {
1818
- const body = await resp.json();
1819
- if (body && typeof body.error === "string")
1820
- detail = body.error;
1821
- } catch {
1822
- detail = await resp.text().catch(() => "");
1561
+ await open_default(authUrl);
1562
+ } catch {
1563
+ v2.message(`If your browser didn't open, paste this URL:
1564
+ ${authUrl}`);
1565
+ }
1566
+ const sp = L2();
1567
+ sp.start("Waiting for you to sign in...");
1568
+ const POLL_INTERVAL = 2000;
1569
+ const TIMEOUT = 5 * 60 * 1000;
1570
+ const start = Date.now();
1571
+ try {
1572
+ while (Date.now() - start < TIMEOUT) {
1573
+ await new Promise((r2) => setTimeout(r2, POLL_INTERVAL));
1574
+ const pollResp = await fetch(`${ZEPHEX_API_BASE}/api/cli/poll?session=${encodeURIComponent(session_id)}`);
1575
+ if (pollResp.status === 410) {
1576
+ throw new Error("Session expired. Please try again.");
1577
+ }
1578
+ if (!pollResp.ok && pollResp.status !== 200) {
1579
+ continue;
1580
+ }
1581
+ const data = await pollResp.json();
1582
+ if (data.status === "complete" && data.key && data.name) {
1583
+ sp.stop("Signed in");
1584
+ return {
1585
+ keyInfo: { key: data.key, name: data.name, created: new Date().toISOString() },
1586
+ email: data.email ?? null
1587
+ };
1588
+ }
1589
+ if (data.status === "error") {
1590
+ throw new Error(data.error || "Authentication failed on server");
1591
+ }
1823
1592
  }
1824
- throw new Error(`create-key failed (${resp.status})${detail ? `: ${detail}` : ""}`);
1825
- }
1826
- const json = await resp.json();
1827
- if (!json || typeof json.key !== "string" || typeof json.name !== "string" || typeof json.created !== "string") {
1828
- throw new Error("create-key returned an unexpected response shape");
1593
+ throw new Error("Timed out waiting for sign-in (5 minutes). Please try again.");
1594
+ } catch (err) {
1595
+ sp.stop("Sign-in failed");
1596
+ throw err;
1829
1597
  }
1830
- return { key: json.key, name: json.name, created: json.created };
1831
1598
  }
1832
1599
  function readJsonFile(filePath) {
1833
1600
  if (!fs7.existsSync(filePath))
@@ -2161,14 +1928,11 @@ async function runSetup(argv) {
2161
1928
  return;
2162
1929
  }
2163
1930
  const resolvedClientId = process.env["AUTH0_CLI_CLIENT_ID"] || DEFAULT_AUTH0_CLI_CLIENT_ID;
2164
- if (!resolvedClientId || resolvedClientId === "AUTH0_CLI_CLIENT_ID_NOT_SET") {
1931
+ if (!resolvedClientId) {
2165
1932
  process.stderr.write(`
2166
1933
  Error: AUTH0_CLI_CLIENT_ID is not configured.
2167
- ` + "Run `node scripts/create-cli-auth0-app.mjs` to create the Auth0 Native\n" + `application, then set AUTH0_CLI_CLIENT_ID in your environment.
2168
- ` + `Alternatively create the app manually in the Auth0 dashboard:
2169
- ` + ` • Application type: Native
2170
- ` + ` • Allowed Callback URLs: http://localhost:52748/callback, http://localhost:52749/callback, http://localhost:52750/callback
2171
- ` + ` • Token Endpoint Auth Method: None
1934
+ ` + `This should not happen with the published package. Report this at:
1935
+ ` + ` https://github.com/zephex/mcp-proxy/issues
2172
1936
 
2173
1937
  `);
2174
1938
  process.exit(1);
@@ -2557,7 +2321,7 @@ if (subcommand === "skills") {
2557
2321
  process.exit(0);
2558
2322
  }
2559
2323
  var { spawn } = await import("node:child_process");
2560
- var __filename2 = fileURLToPath3(import.meta.url);
2324
+ var __filename2 = fileURLToPath2(import.meta.url);
2561
2325
  var __dirname3 = dirname(__filename2);
2562
2326
  var serverPath = resolve(__dirname3, "tools/server.js");
2563
2327
  var child = spawn(process.execPath, [serverPath], {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zephex",
3
- "version": "2.1.1",
3
+ "version": "2.1.3",
4
4
  "description": "Zephex MCP — codebase intelligence tools for AI coding agents. stdio server that runs locally, reads your project files, and proxies AI calls to the Zephex backend.",
5
5
  "type": "module",
6
6
  "main": "dist/cli.js",