memax-cli 0.1.0-alpha.26 → 0.1.0-alpha.28

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 (37) hide show
  1. package/dist/commands/mcp.d.ts.map +1 -1
  2. package/dist/commands/mcp.js +8 -2
  3. package/dist/commands/mcp.js.map +1 -1
  4. package/dist/commands/recall.d.ts +5 -0
  5. package/dist/commands/recall.d.ts.map +1 -1
  6. package/dist/commands/recall.js +89 -6
  7. package/dist/commands/recall.js.map +1 -1
  8. package/dist/commands/recall.test.d.ts +2 -0
  9. package/dist/commands/recall.test.d.ts.map +1 -0
  10. package/dist/commands/recall.test.js +23 -0
  11. package/dist/commands/recall.test.js.map +1 -0
  12. package/dist/commands/setup-mcp.d.ts.map +1 -1
  13. package/dist/commands/setup-mcp.js +3 -3
  14. package/dist/commands/setup-mcp.js.map +1 -1
  15. package/dist/commands/sync.d.ts +26 -0
  16. package/dist/commands/sync.d.ts.map +1 -1
  17. package/dist/commands/sync.js +508 -79
  18. package/dist/commands/sync.js.map +1 -1
  19. package/dist/commands/sync.test.d.ts +2 -0
  20. package/dist/commands/sync.test.d.ts.map +1 -0
  21. package/dist/commands/sync.test.js +130 -0
  22. package/dist/commands/sync.test.js.map +1 -0
  23. package/dist/index.js +9 -1
  24. package/dist/index.js.map +1 -1
  25. package/dist/lib/config.d.ts +33 -0
  26. package/dist/lib/config.d.ts.map +1 -1
  27. package/dist/lib/config.js +63 -0
  28. package/dist/lib/config.js.map +1 -1
  29. package/dist/lib/project-context.d.ts +14 -4
  30. package/dist/lib/project-context.d.ts.map +1 -1
  31. package/dist/lib/project-context.js +98 -54
  32. package/dist/lib/project-context.js.map +1 -1
  33. package/dist/lib/project-context.test.d.ts +2 -0
  34. package/dist/lib/project-context.test.d.ts.map +1 -0
  35. package/dist/lib/project-context.test.js +75 -0
  36. package/dist/lib/project-context.test.js.map +1 -0
  37. package/package.json +2 -2
@@ -29,40 +29,105 @@ export function normalizeRepoUrl(url) {
29
29
  s = s.toLowerCase().replace(/\\/g, "/");
30
30
  return s;
31
31
  }
32
- /**
33
- * Get a canonical project scope string for the given directory.
34
- *
35
- * Returns:
36
- * "project:<normalized-repo-url>" — git remote available (best)
37
- * "project:<dirname>" — git repo but no remote
38
- * "project" — no git at all (legacy fallback)
39
- */
40
- export function getProjectScope(dir) {
32
+ function normalizeProjectID(projectID) {
33
+ let s = projectID.trim();
34
+ s = s.replace(/^project:/, "");
35
+ s = normalizeRepoUrl(s);
36
+ if (!s || /\s/.test(s)) {
37
+ throw new Error("invalid project_id");
38
+ }
39
+ return s;
40
+ }
41
+ function findNearestMemaxYml(startDir) {
42
+ let dir = startDir;
43
+ const root = "/";
44
+ while (true) {
45
+ const ymlPath = join(dir, ".memax.yml");
46
+ if (existsSync(ymlPath)) {
47
+ return ymlPath;
48
+ }
49
+ const parent = join(dir, "..");
50
+ if (parent === dir || dir === root)
51
+ break;
52
+ dir = parent;
53
+ }
54
+ return null;
55
+ }
56
+ export function readMemaxYmlConfig(dir) {
41
57
  const cwd = dir ?? process.cwd();
58
+ const ymlPath = findNearestMemaxYml(cwd);
59
+ if (!ymlPath) {
60
+ return undefined;
61
+ }
42
62
  try {
43
- const repo = execSync("git remote get-url origin", {
44
- cwd,
45
- encoding: "utf-8",
46
- timeout: 2000,
47
- stdio: ["pipe", "pipe", "pipe"],
48
- }).trim();
49
- if (repo)
50
- return `project:${normalizeRepoUrl(repo)}`;
63
+ const content = readFileSync(ymlPath, "utf-8");
64
+ const hubMatch = content.match(/^hub:\s*(.+)$/m);
65
+ const projectMatch = content.match(/^project_id:\s*(.+)$/m);
66
+ const cfg = {};
67
+ if (hubMatch) {
68
+ cfg.hub = hubMatch[1].trim();
69
+ }
70
+ if (projectMatch) {
71
+ cfg.project_id = normalizeProjectID(projectMatch[1].trim());
72
+ }
73
+ if (!cfg.hub && !cfg.project_id) {
74
+ return undefined;
75
+ }
76
+ return cfg;
51
77
  }
52
- catch { }
78
+ catch {
79
+ return undefined;
80
+ }
81
+ }
82
+ function getGitOriginProjectID(cwd) {
53
83
  try {
54
- const root = execSync("git rev-parse --show-toplevel", {
84
+ const repo = execSync("git remote get-url origin", {
55
85
  cwd,
56
86
  encoding: "utf-8",
57
87
  timeout: 2000,
58
88
  stdio: ["pipe", "pipe", "pipe"],
59
89
  }).trim();
60
- const name = root.split("/").pop();
61
- if (name)
62
- return `project:${name.toLowerCase()}`;
90
+ if (repo) {
91
+ return normalizeRepoUrl(repo);
92
+ }
63
93
  }
64
94
  catch { }
65
- return "project";
95
+ return undefined;
96
+ }
97
+ /**
98
+ * Get a canonical project scope string for the given directory.
99
+ *
100
+ * Returns:
101
+ * "project:<project-id>" — .memax.yml project_id or git remote available
102
+ * "project" — no canonical cross-device project identity
103
+ */
104
+ export function getProjectScope(dir) {
105
+ return resolveProjectScope(dir).scope;
106
+ }
107
+ export function resolveProjectScope(dir) {
108
+ const cwd = dir ?? process.cwd();
109
+ const memaxCfg = readMemaxYmlConfig(cwd);
110
+ const gitProjectID = getGitOriginProjectID(cwd);
111
+ if (memaxCfg?.project_id) {
112
+ const warning = gitProjectID && gitProjectID !== memaxCfg.project_id
113
+ ? `.memax.yml project_id (${memaxCfg.project_id}) overrides git origin (${gitProjectID})`
114
+ : undefined;
115
+ return {
116
+ scope: `project:${memaxCfg.project_id}`,
117
+ source: "memax_yml",
118
+ warning,
119
+ };
120
+ }
121
+ if (gitProjectID) {
122
+ return {
123
+ scope: `project:${gitProjectID}`,
124
+ source: "git_remote",
125
+ };
126
+ }
127
+ return {
128
+ scope: "project",
129
+ source: "fallback",
130
+ };
66
131
  }
67
132
  /**
68
133
  * Resolve a Claude Code mangled project folder name to a normalized repo URL.
@@ -78,18 +143,11 @@ export function resolveClaudeProjectFolder(mangledName) {
78
143
  const absolutePath = mangledName.replace(/-/g, "/");
79
144
  if (!existsSync(absolutePath))
80
145
  return null;
81
- try {
82
- const repo = execSync("git remote get-url origin", {
83
- cwd: absolutePath,
84
- encoding: "utf-8",
85
- timeout: 2000,
86
- stdio: ["pipe", "pipe", "pipe"],
87
- }).trim();
88
- if (repo)
89
- return normalizeRepoUrl(repo);
146
+ const resolution = resolveProjectScope(absolutePath);
147
+ if (resolution.scope === "project") {
148
+ return null;
90
149
  }
91
- catch { }
92
- return null;
150
+ return resolution.scope.replace(/^project:/, "");
93
151
  }
94
152
  /**
95
153
  * Normalize a file path for cross-platform consistency.
@@ -101,10 +159,12 @@ export function normalizeFilePath(p) {
101
159
  return p.replace(/\\/g, "/").replace(/^\.\//, "").replace(/\/+/g, "/");
102
160
  }
103
161
  /** Detect git project context (repo URL, project name, branch). */
104
- export function detectProjectContext() {
162
+ export function detectProjectContext(dir) {
163
+ const cwd = dir ?? process.cwd();
105
164
  const ctx = {};
106
165
  try {
107
166
  const repo = execSync("git remote get-url origin", {
167
+ cwd,
108
168
  encoding: "utf-8",
109
169
  timeout: 2000,
110
170
  }).trim();
@@ -114,6 +174,7 @@ export function detectProjectContext() {
114
174
  catch { }
115
175
  try {
116
176
  const project = execSync("git rev-parse --show-toplevel", {
177
+ cwd,
117
178
  encoding: "utf-8",
118
179
  timeout: 2000,
119
180
  }).trim();
@@ -123,6 +184,7 @@ export function detectProjectContext() {
123
184
  catch { }
124
185
  try {
125
186
  const branch = execSync("git branch --show-current", {
187
+ cwd,
126
188
  encoding: "utf-8",
127
189
  timeout: 2000,
128
190
  }).trim();
@@ -134,24 +196,6 @@ export function detectProjectContext() {
134
196
  }
135
197
  /** Walk up from cwd looking for .memax.yml with a hub field. */
136
198
  export function readMemaxYmlHub() {
137
- let dir = process.cwd();
138
- const root = "/";
139
- while (true) {
140
- const ymlPath = join(dir, ".memax.yml");
141
- if (existsSync(ymlPath)) {
142
- try {
143
- const content = readFileSync(ymlPath, "utf-8");
144
- const match = content.match(/^hub:\s*(.+)$/m);
145
- if (match)
146
- return match[1].trim();
147
- }
148
- catch { }
149
- }
150
- const parent = join(dir, "..");
151
- if (parent === dir || dir === root)
152
- break;
153
- dir = parent;
154
- }
155
- return undefined;
199
+ return readMemaxYmlConfig()?.hub;
156
200
  }
157
201
  //# sourceMappingURL=project-context.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"project-context.js","sourceRoot":"","sources":["../../src/lib/project-context.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"project-context.js","sourceRoot":"","sources":["../../src/lib/project-context.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=project-context.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-context.test.d.ts","sourceRoot":"","sources":["../../src/lib/project-context.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,75 @@
1
+ import { beforeEach, describe, expect, it, vi } from "vitest";
2
+ const { execSync, existsSync, readFileSync } = vi.hoisted(() => ({
3
+ execSync: vi.fn(),
4
+ existsSync: vi.fn(),
5
+ readFileSync: vi.fn(),
6
+ }));
7
+ vi.mock("node:child_process", () => ({
8
+ execSync,
9
+ }));
10
+ vi.mock("node:fs", async () => {
11
+ const actual = await vi.importActual("node:fs");
12
+ return {
13
+ ...actual,
14
+ existsSync,
15
+ readFileSync,
16
+ };
17
+ });
18
+ import { getProjectScope, normalizeRepoUrl, readMemaxYmlConfig, readMemaxYmlHub, resolveProjectScope, } from "./project-context.js";
19
+ describe("normalizeRepoUrl", () => {
20
+ it("normalizes common git remote forms", () => {
21
+ expect(normalizeRepoUrl("https://github.com/MemaxLabs/memax.git")).toBe("github.com/memaxlabs/memax");
22
+ expect(normalizeRepoUrl("git@github.com:MemaxLabs/memax.git")).toBe("github.com/memaxlabs/memax");
23
+ expect(normalizeRepoUrl("ssh://git@github.com/MemaxLabs/memax")).toBe("github.com/memaxlabs/memax");
24
+ });
25
+ });
26
+ describe("getProjectScope", () => {
27
+ beforeEach(() => {
28
+ execSync.mockReset();
29
+ existsSync.mockReset();
30
+ readFileSync.mockReset();
31
+ existsSync.mockReturnValue(false);
32
+ });
33
+ it("uses the normalized origin remote when present", () => {
34
+ execSync.mockReturnValueOnce("git@github.com:MemaxLabs/memax.git\n");
35
+ expect(getProjectScope("/workspaces/memax")).toBe("project:github.com/memaxlabs/memax");
36
+ });
37
+ it("returns generic project scope when there is no canonical remote", () => {
38
+ execSync.mockImplementation(() => {
39
+ throw new Error("no remote");
40
+ });
41
+ expect(getProjectScope("/workspaces/memax")).toBe("project");
42
+ });
43
+ it("uses .memax.yml project_id as an explicit override", () => {
44
+ existsSync.mockImplementation((path) => path.endsWith(".memax.yml"));
45
+ readFileSync.mockReturnValue("project_id: Acme.Internal/Payments-API\n");
46
+ expect(getProjectScope("/workspaces/memax")).toBe("project:acme.internal/payments-api");
47
+ });
48
+ it("reports when .memax.yml project_id overrides git origin", () => {
49
+ existsSync.mockImplementation((path) => path.endsWith(".memax.yml"));
50
+ readFileSync.mockReturnValue("project_id: github.com/acme/override\n");
51
+ execSync.mockReturnValueOnce("git@github.com:MemaxLabs/memax.git\n");
52
+ expect(resolveProjectScope("/workspaces/memax")).toEqual({
53
+ scope: "project:github.com/acme/override",
54
+ source: "memax_yml",
55
+ warning: ".memax.yml project_id (github.com/acme/override) overrides git origin (github.com/memaxlabs/memax)",
56
+ });
57
+ });
58
+ });
59
+ describe("readMemaxYmlConfig", () => {
60
+ beforeEach(() => {
61
+ existsSync.mockReset();
62
+ readFileSync.mockReset();
63
+ existsSync.mockReturnValue(false);
64
+ });
65
+ it("parses hub and project_id from .memax.yml", () => {
66
+ existsSync.mockImplementation((path) => path.endsWith(".memax.yml"));
67
+ readFileSync.mockReturnValue("hub: team-backend\nproject_id: github.com/MemaxLabs/memax\n");
68
+ expect(readMemaxYmlConfig("/workspaces/memax")).toEqual({
69
+ hub: "team-backend",
70
+ project_id: "github.com/memaxlabs/memax",
71
+ });
72
+ expect(readMemaxYmlHub()).toBe("team-backend");
73
+ });
74
+ });
75
+ //# sourceMappingURL=project-context.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-context.test.js","sourceRoot":"","sources":["../../src/lib/project-context.test.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "memax-cli",
3
- "version": "0.1.0-alpha.26",
3
+ "version": "0.1.0-alpha.28",
4
4
  "description": "CLI for Memax — universal context & memory hub for AI agents",
5
5
  "type": "module",
6
6
  "bin": {
@@ -16,7 +16,7 @@
16
16
  "@modelcontextprotocol/sdk": "^1.12.1",
17
17
  "chalk": "^5.4.0",
18
18
  "commander": "^13.0.0",
19
- "memax-sdk": "^0.1.2"
19
+ "memax-sdk": "^0.1.3"
20
20
  },
21
21
  "devDependencies": {
22
22
  "@types/node": "^25.5.0",