@memmo/cli 0.7.2 → 0.7.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/index.js +42 -15
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -109,7 +109,15 @@ function forgetRepo(remote) {
109
109
  } catch {
110
110
  }
111
111
  }
112
- var DEFAULT_API_BASE_URL = process.env.MEMMO_API_URL ?? "https://api.memmo.dev";
112
+ function envApiUrl() {
113
+ const v = process.env.MEMMO_API_URL?.trim();
114
+ return v ? v.replace(/\/$/, "") : void 0;
115
+ }
116
+ function envToken() {
117
+ const v = process.env.MEMMO_TOKEN?.trim();
118
+ return v || void 0;
119
+ }
120
+ var DEFAULT_API_BASE_URL = envApiUrl() ?? "https://api.memmo.dev";
113
121
  function detectGitRemote(cwd = process.cwd()) {
114
122
  try {
115
123
  return execSync("git remote get-url origin", {
@@ -122,11 +130,12 @@ function detectGitRemote(cwd = process.cwd()) {
122
130
  }
123
131
  async function resolveProjectConfig(cwd = process.cwd(), opts = {}) {
124
132
  const creds = loadCredentials();
125
- const apiBaseUrl = opts.apiBaseUrl ?? process.env.MEMMO_API_URL ?? creds?.apiBaseUrl ?? DEFAULT_API_BASE_URL;
133
+ const apiBaseUrl = opts.apiBaseUrl ?? envApiUrl() ?? creds?.apiBaseUrl ?? DEFAULT_API_BASE_URL;
134
+ const token = envToken() ?? creds?.token;
126
135
  const explicit = opts.repoId ?? process.env.MEMMO_REPO_ID;
127
136
  if (explicit) return { apiBaseUrl, repoId: explicit };
128
137
  const remote = detectGitRemote(cwd);
129
- if (remote && creds) {
138
+ if (remote && token) {
130
139
  const hit = readRepoCache()[remote];
131
140
  if (hit && hit.apiBaseUrl === apiBaseUrl && Date.now() - hit.at < REPO_CACHE_TTL_MS) {
132
141
  return { apiBaseUrl, repoId: hit.repoId, repoFullName: hit.fullName };
@@ -134,7 +143,7 @@ async function resolveProjectConfig(cwd = process.cwd(), opts = {}) {
134
143
  try {
135
144
  const { apiFetch: apiFetch2 } = await Promise.resolve().then(() => (init_api(), api_exports));
136
145
  const r = await apiFetch2(
137
- { baseUrl: apiBaseUrl, token: creds.token },
146
+ { baseUrl: apiBaseUrl, token },
138
147
  "/repos/resolve",
139
148
  { method: "POST", body: JSON.stringify({ repoRemote: remote }) }
140
149
  );
@@ -612,7 +621,7 @@ async function desktopCommand(opts = {}) {
612
621
  }
613
622
  const creds = loadCredentials();
614
623
  if (!creds) throw new Error("Not logged in. Run `memmo login` first.");
615
- const client = { baseUrl: process.env.MEMMO_API_URL ?? creds.apiBaseUrl, token: creds.token };
624
+ const client = { baseUrl: envApiUrl() ?? creds.apiBaseUrl, token: creds.token };
616
625
  let repoId = opts.repo;
617
626
  let label = repoId;
618
627
  if (!repoId) {
@@ -675,7 +684,7 @@ async function chooseProject(client, wanted, yes = false) {
675
684
  async function initCommand(opts) {
676
685
  const creds = loadCredentials();
677
686
  if (!creds) throw new Error("Not logged in. Run `memmo login` first.");
678
- const client = { baseUrl: process.env.MEMMO_API_URL ?? creds.apiBaseUrl, token: creds.token };
687
+ const client = { baseUrl: envApiUrl() ?? creds.apiBaseUrl, token: creds.token };
679
688
  const cwd = process.cwd();
680
689
  if (!existsSync5(join5(cwd, ".git"))) {
681
690
  console.log("note: no .git here \u2014 run `memmo init` at your repo root.");
@@ -1856,15 +1865,21 @@ async function postInlineReview(ctx, diff, review) {
1856
1865
  `Memmo: posted review (${payload.comments.length} inline, ${payload.newCount} new findings).`
1857
1866
  );
1858
1867
  }
1868
+ function skipReview(message) {
1869
+ console.error(message);
1870
+ if (!process.env.GITHUB_ACTIONS) process.exitCode = 1;
1871
+ }
1859
1872
  async function reviewCommand(opts = {}) {
1860
1873
  const config = await resolveProjectConfig();
1861
1874
  if (!config) {
1862
- throw new Error(NOT_CONNECTED);
1875
+ return skipReview(
1876
+ process.env.GITHUB_ACTIONS ? "Memmo: this repo isn't connected to a project, or MEMMO_TOKEN isn't a token for it. Open Memmo \u2192 Reviews to fix; skipping the review." : NOT_CONNECTED
1877
+ );
1863
1878
  }
1864
1879
  const creds = loadCredentials();
1865
- const token = process.env.MEMMO_TOKEN ?? creds?.token;
1880
+ const token = envToken() ?? creds?.token;
1866
1881
  if (!token) throw new Error("No API token. Set MEMMO_TOKEN (CI) or run `memmo login`.");
1867
- const baseUrl = opts.api ?? process.env.MEMMO_API_URL ?? config.apiBaseUrl ?? creds?.apiBaseUrl;
1882
+ const baseUrl = opts.api ?? envApiUrl() ?? config.apiBaseUrl ?? creds?.apiBaseUrl;
1868
1883
  if (!baseUrl) throw new Error("No API base URL. Set MEMMO_API_URL or pass --api.");
1869
1884
  const client = { baseUrl, token };
1870
1885
  const base = opts.base ?? process.env.GITHUB_BASE_REF ?? "main";
@@ -1876,10 +1891,22 @@ async function reviewCommand(opts = {}) {
1876
1891
  const ev = readEvent();
1877
1892
  const prTitle = (opts.title ?? ev.title ?? git(["log", "-1", "--pretty=%s"]).trim()).slice(0, 500);
1878
1893
  const prBody = opts.body ?? ev.body;
1879
- const res = await apiFetch(client, `/repos/${config.repoId}/review-diff`, {
1880
- method: "POST",
1881
- body: JSON.stringify({ prTitle, prBody, diff })
1882
- });
1894
+ let res;
1895
+ try {
1896
+ res = await apiFetch(client, `/repos/${config.repoId}/review-diff`, {
1897
+ method: "POST",
1898
+ body: JSON.stringify({ prTitle, prBody, diff })
1899
+ });
1900
+ } catch (e) {
1901
+ const msg = e instanceof Error ? e.message : String(e);
1902
+ if (msg.includes("llm_not_configured")) {
1903
+ return skipReview("Memmo: the project has no AI key yet. Add one in Memmo \u2192 Reviews (step 1); skipping the review.");
1904
+ }
1905
+ if (msg.includes("plan_requires_reviewer")) {
1906
+ return skipReview("Memmo: the PR reviewer needs the Scale plan. Upgrade in Memmo \u2192 Settings \u2192 Subscription; skipping the review.");
1907
+ }
1908
+ throw e;
1909
+ }
1883
1910
  if (res.skipped) {
1884
1911
  console.error("Memmo reviewer is disabled for this repo \u2014 skipping (enable it in the dashboard).");
1885
1912
  return;
@@ -1933,9 +1960,9 @@ async function reviewSyncCommand(opts = {}) {
1933
1960
  throw new Error(NOT_CONNECTED);
1934
1961
  }
1935
1962
  const creds = loadCredentials();
1936
- const token = process.env.MEMMO_TOKEN ?? creds?.token;
1963
+ const token = envToken() ?? creds?.token;
1937
1964
  if (!token) throw new Error("No API token. Set MEMMO_TOKEN (CI) or run `memmo login`.");
1938
- const baseUrl = opts.api ?? process.env.MEMMO_API_URL ?? config.apiBaseUrl ?? creds?.apiBaseUrl;
1965
+ const baseUrl = opts.api ?? envApiUrl() ?? config.apiBaseUrl ?? creds?.apiBaseUrl;
1939
1966
  if (!baseUrl) throw new Error("No API base URL. Set MEMMO_API_URL or pass --api.");
1940
1967
  const client = { baseUrl, token };
1941
1968
  const ev = readEvent();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@memmo/cli",
3
- "version": "0.7.2",
3
+ "version": "0.7.3",
4
4
  "description": "Long-term memory for AI coding agents — CLI + MCP server for Claude Code.",
5
5
  "license": "MIT",
6
6
  "author": "Benjamin Beguin",