@codemap-ai/cli 0.1.5 → 0.1.8

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.
@@ -4,8 +4,9 @@ import {
4
4
  __require,
5
5
  __toESM,
6
6
  createCodeMapClient,
7
+ findMonorepoRoot,
7
8
  loadConfig
8
- } from "./chunk-AXGGL47C.js";
9
+ } from "./chunk-4F6G2Q7W.js";
9
10
 
10
11
  // ../code-index/dist/language-utils.js
11
12
  var require_language_utils = __commonJS({
@@ -215409,7 +215410,7 @@ var require_dist = __commonJS({
215409
215410
  }
215410
215411
  });
215411
215412
 
215412
- // src/lib/workspace-git.ts
215413
+ // ../core/src/lib/workspace-git.ts
215413
215414
  import { execFile } from "child_process";
215414
215415
  import path from "path";
215415
215416
  import { promisify } from "util";
@@ -215462,14 +215463,14 @@ async function getCurrentWorkspaceInfo(cwd = process.cwd()) {
215462
215463
  };
215463
215464
  }
215464
215465
 
215465
- // src/lib/local-index.ts
215466
+ // ../core/src/lib/local-index.ts
215466
215467
  var import_code_index = __toESM(require_dist(), 1);
215467
215468
  import path5 from "path";
215468
215469
 
215469
- // src/lib/workspace-resolver.ts
215470
+ // ../core/src/lib/workspace-resolver.ts
215470
215471
  import path3 from "path";
215471
215472
 
215472
- // src/lib/workspace-project.ts
215473
+ // ../core/src/lib/workspace-project.ts
215473
215474
  import path2 from "path";
215474
215475
  import { access, mkdir, readFile, writeFile } from "fs/promises";
215475
215476
  var WORKSPACE_CONFIG_FILE = ".codemap/mcp.json";
@@ -215479,21 +215480,30 @@ async function readWorkspaceProjectConfigAt(configPath) {
215479
215480
  let mcpServers;
215480
215481
  if (parsed.mcpServers && typeof parsed.mcpServers === "object" && !Array.isArray(parsed.mcpServers)) {
215481
215482
  mcpServers = {};
215482
- for (const [name, config] of Object.entries(parsed.mcpServers)) {
215483
+ for (const [name, config] of Object.entries(
215484
+ parsed.mcpServers
215485
+ )) {
215483
215486
  if (config && typeof config === "object" && !Array.isArray(config)) {
215484
215487
  const sc = config;
215485
215488
  const entry = {};
215486
215489
  if (typeof sc.type === "string") entry.type = sc.type;
215487
215490
  if (typeof sc.command === "string") entry.command = sc.command;
215488
- if (Array.isArray(sc.args)) entry.args = sc.args.filter((a) => typeof a === "string");
215491
+ if (Array.isArray(sc.args))
215492
+ entry.args = sc.args.filter(
215493
+ (a) => typeof a === "string"
215494
+ );
215489
215495
  if (sc.env && typeof sc.env === "object" && !Array.isArray(sc.env)) {
215490
215496
  entry.env = {};
215491
- for (const [k, v] of Object.entries(sc.env)) {
215497
+ for (const [k, v] of Object.entries(
215498
+ sc.env
215499
+ )) {
215492
215500
  if (typeof v === "string") entry.env[k] = v;
215493
215501
  }
215494
215502
  }
215495
215503
  if (Array.isArray(sc.priorityResources)) {
215496
- entry.priorityResources = sc.priorityResources.filter((r) => typeof r === "string");
215504
+ entry.priorityResources = sc.priorityResources.filter(
215505
+ (r) => typeof r === "string"
215506
+ );
215497
215507
  }
215498
215508
  mcpServers[name] = entry;
215499
215509
  }
@@ -215529,6 +215539,10 @@ async function readWorkspaceProjectConfig(cwd = process.cwd()) {
215529
215539
  resolvedRepoRoot ??= workspace.repoRootPath;
215530
215540
  }
215531
215541
  }
215542
+ try {
215543
+ candidateRoots.add(await findMonorepoRoot(cwd));
215544
+ } catch {
215545
+ }
215532
215546
  for (const root of candidateRoots) {
215533
215547
  try {
215534
215548
  const config = await readWorkspaceProjectConfigAt(
@@ -215551,42 +215565,39 @@ async function readPriorityResources(serverName = "codemap", cwd = process.cwd()
215551
215565
  const config = await readWorkspaceProjectConfig(cwd);
215552
215566
  return config.mcpServers?.[serverName]?.priorityResources ?? [];
215553
215567
  }
215554
- async function readMcpServerConfigs(cwd = process.cwd()) {
215568
+ async function readMcpServerConfigs(cwd = process.cwd(), globalMcpServers) {
215555
215569
  const config = await readWorkspaceProjectConfig(cwd);
215556
215570
  const result = /* @__PURE__ */ new Map();
215557
- if (!config.mcpServers) return result;
215558
- for (const [name, entry] of Object.entries(config.mcpServers)) {
215559
- if (entry.command) {
215560
- result.set(name, { command: entry.command, args: entry.args, env: entry.env });
215571
+ if (globalMcpServers) {
215572
+ for (const [name, entry] of Object.entries(globalMcpServers)) {
215573
+ if (entry.command) {
215574
+ result.set(name, {
215575
+ command: entry.command,
215576
+ args: entry.args,
215577
+ env: entry.env
215578
+ });
215579
+ }
215580
+ }
215581
+ }
215582
+ if (config.mcpServers) {
215583
+ for (const [name, entry] of Object.entries(config.mcpServers)) {
215584
+ if (entry.command) {
215585
+ result.set(name, {
215586
+ command: entry.command,
215587
+ args: entry.args,
215588
+ env: entry.env
215589
+ });
215590
+ }
215561
215591
  }
215562
215592
  }
215563
215593
  return result;
215564
215594
  }
215565
- async function readWorkspaceProjectId(cwd = process.cwd()) {
215566
- return (await readWorkspaceProjectConfig(cwd)).projectId;
215567
- }
215568
215595
  async function readWorkspacePath(cwd = process.cwd()) {
215569
215596
  const config = await readWorkspaceProjectConfig(cwd);
215570
215597
  if (config.workspaceRootPath) return config.workspaceRootPath;
215571
215598
  const workspace = await tryGetCurrentWorkspaceInfo(cwd);
215572
215599
  return workspace?.repoRootPath ?? cwd;
215573
215600
  }
215574
- async function saveWorkspaceProjectId(workspaceRoot, projectId) {
215575
- const configPath = path2.join(workspaceRoot, WORKSPACE_CONFIG_FILE);
215576
- let existing = {};
215577
- try {
215578
- const raw = await readFile(configPath, "utf8");
215579
- existing = JSON.parse(raw);
215580
- } catch {
215581
- }
215582
- await mkdir(path2.dirname(configPath), { recursive: true });
215583
- await writeFile(
215584
- configPath,
215585
- `${JSON.stringify({ ...existing, projectId, workspaceRootPath: workspaceRoot }, null, 2)}
215586
- `,
215587
- "utf8"
215588
- );
215589
- }
215590
215601
  async function saveMcpServerEntry(workspaceRoot, name, entry) {
215591
215602
  const configPath = path2.join(workspaceRoot, WORKSPACE_CONFIG_FILE);
215592
215603
  let existing = {};
@@ -215618,16 +215629,12 @@ async function removeMcpServerEntry(workspaceRoot, name) {
215618
215629
  if (!(name in mcpServers)) return false;
215619
215630
  delete mcpServers[name];
215620
215631
  existing.mcpServers = mcpServers;
215621
- await writeFile(
215622
- configPath,
215623
- `${JSON.stringify(existing, null, 2)}
215624
- `,
215625
- "utf8"
215626
- );
215632
+ await writeFile(configPath, `${JSON.stringify(existing, null, 2)}
215633
+ `, "utf8");
215627
215634
  return true;
215628
215635
  }
215629
215636
 
215630
- // src/lib/workspace-resolver.ts
215637
+ // ../core/src/lib/workspace-resolver.ts
215631
215638
  async function resolveWorkspace(input) {
215632
215639
  const cwd = input?.cwd ?? process.cwd();
215633
215640
  const envWorkspaceRoot = process.env.WORKSPACE_ROOT?.trim() || null;
@@ -215649,6 +215656,13 @@ async function resolveWorkspace(input) {
215649
215656
  resolution: "project_local_path"
215650
215657
  });
215651
215658
  }
215659
+ try {
215660
+ const monorepoRoot = await findMonorepoRoot(cwd);
215661
+ if (monorepoRoot !== cwd) {
215662
+ candidates.push({ path: monorepoRoot, resolution: "monorepo" });
215663
+ }
215664
+ } catch {
215665
+ }
215652
215666
  const seen = /* @__PURE__ */ new Set();
215653
215667
  for (const candidate of candidates) {
215654
215668
  const candidatePath = path3.resolve(candidate.path);
@@ -215672,7 +215686,7 @@ async function resolveWorkspace(input) {
215672
215686
  };
215673
215687
  }
215674
215688
 
215675
- // src/lib/import-health.ts
215689
+ // ../core/src/lib/import-health.ts
215676
215690
  function normalizeRepositoryUrl(value) {
215677
215691
  const trimmed = value.trim().replace(/\.git$/i, "").replace(/\/+$/, "");
215678
215692
  const githubSshMatch = /^git@github\.com:(.+)$/i.exec(trimmed);
@@ -215697,9 +215711,6 @@ function shouldCompareWorkspaceCommit(project, workspace) {
215697
215711
  project.localWorkspacePath && workspace.repoRootPath && project.localWorkspacePath === workspace.repoRootPath
215698
215712
  );
215699
215713
  }
215700
- function isImportDone(status) {
215701
- return status === "completed" || status === "failed";
215702
- }
215703
215714
  async function fetchLatestProjectImport(client, projectId) {
215704
215715
  const imports = await client.request(
215705
215716
  `/projects/${encodeURIComponent(projectId)}/imports`,
@@ -215826,22 +215837,8 @@ async function getProjectImportHealth(client, projectId, project) {
215826
215837
  project
215827
215838
  });
215828
215839
  }
215829
- function formatShortCommit(commit) {
215830
- return commit ? commit.slice(0, 8) : null;
215831
- }
215832
- function describeImportHealth(health) {
215833
- const lines = [
215834
- `Index health: ${health.state}`,
215835
- health.latestImport?.commitSha ? `Import commit: ${formatShortCommit(health.latestImport.commitSha)}` : null,
215836
- health.workspace?.commitSha ? `Local commit: ${formatShortCommit(health.workspace.commitSha)}` : null,
215837
- health.workspaceResolution ? `Workspace: ${health.workspaceResolution}` : null,
215838
- health.commitComparison.status === "different" ? "Local workspace differs from the latest indexed commit." : null,
215839
- health.nextAction !== "none" ? `Next action: ${health.nextAction}` : null
215840
- ];
215841
- return lines.filter(Boolean).join("\n");
215842
- }
215843
215840
 
215844
- // src/lib/sqlite-index-store.ts
215841
+ // ../core/src/lib/sqlite-index-store.ts
215845
215842
  import { DatabaseSync } from "node:sqlite";
215846
215843
  import { existsSync, mkdirSync } from "fs";
215847
215844
  import path4 from "path";
@@ -216543,7 +216540,7 @@ var SQLiteIndexStore = class _SQLiteIndexStore {
216543
216540
  }
216544
216541
  };
216545
216542
 
216546
- // src/lib/local-index.ts
216543
+ // ../core/src/lib/local-index.ts
216547
216544
  var _cachedStore = null;
216548
216545
  function toLocalFile(file, semantics) {
216549
216546
  return {
@@ -216692,49 +216689,11 @@ async function removeLocalFile(relativePath, workspaceRootPath) {
216692
216689
  _cachedStore = null;
216693
216690
  return removed;
216694
216691
  }
216695
- async function getLocalIndexSummary(store) {
216696
- const files = await collectFilesForStore(store);
216697
- return store.getSummary(files.length > 0 ? store.isStale(files) : false);
216698
- }
216699
216692
  async function ensureLocalIndexWithSummary(input) {
216700
216693
  const store = await ensureLocalIndex(input);
216701
216694
  const summary = store.getSummary(false);
216702
216695
  return { store, summary };
216703
216696
  }
216704
- function isCloudContentEmpty(content) {
216705
- return content?.status === "ready" && !content.content;
216706
- }
216707
- function shouldFallbackToLocal(error) {
216708
- const message = error instanceof Error ? error.message : String(error);
216709
- return message.includes("Not authenticated") || message.includes("Failed to reach CodeMap API") || message.includes("CodeMap API returned 401") || message.includes("CodeMap API returned 403") || message.includes("CodeMap API returned 404") || message.includes("CodeMap API returned 409") || message.includes("CodeMap API returned 422") || message.includes("Unexpected response from API");
216710
- }
216711
- async function shouldUseLocalIndexBeforeRemote(client, projectId) {
216712
- try {
216713
- const [latestImport, workspace] = await Promise.all([
216714
- fetchLatestProjectImport(client, projectId),
216715
- resolveWorkspace()
216716
- ]);
216717
- if (!latestImport) return true;
216718
- if (latestImport.status !== "completed" || latestImport.parseStatus !== "completed") {
216719
- return true;
216720
- }
216721
- if (latestImport.commitSha && workspace.workspace?.commitSha && latestImport.commitSha !== workspace.workspace.commitSha) {
216722
- return true;
216723
- }
216724
- return false;
216725
- } catch (error) {
216726
- return shouldFallbackToLocal(error);
216727
- }
216728
- }
216729
- function toRepoRelativePath(filePath, workspaceRootPath) {
216730
- const normalized = path5.normalize(filePath);
216731
- const root = path5.normalize(workspaceRootPath);
216732
- if (path5.isAbsolute(normalized) && normalized.startsWith(root)) {
216733
- const rel = normalized.slice(root.length);
216734
- return rel.startsWith(path5.sep) ? rel.slice(1) : rel;
216735
- }
216736
- return filePath;
216737
- }
216738
216697
 
216739
216698
  // src/commands/status.ts
216740
216699
  function formatAge(date) {
@@ -218193,32 +218152,18 @@ async function switchMastraThread(threadId) {
218193
218152
 
218194
218153
  export {
218195
218154
  tryGetCurrentWorkspaceInfo,
218196
- readWorkspaceProjectConfig,
218197
218155
  readPriorityResources,
218198
218156
  readMcpServerConfigs,
218199
- readWorkspaceProjectId,
218200
218157
  readWorkspacePath,
218201
- saveWorkspaceProjectId,
218202
218158
  saveMcpServerEntry,
218203
218159
  removeMcpServerEntry,
218204
- resolveWorkspace,
218205
- isImportDone,
218206
- buildImportHealth,
218207
- getProjectImportHealth,
218208
- formatShortCommit,
218209
- describeImportHealth,
218210
218160
  require_dist,
218211
218161
  buildLocalIndex,
218212
218162
  readLocalIndex,
218213
218163
  ensureLocalIndex,
218214
218164
  refreshLocalFile,
218215
218165
  removeLocalFile,
218216
- getLocalIndexSummary,
218217
218166
  ensureLocalIndexWithSummary,
218218
- isCloudContentEmpty,
218219
- shouldFallbackToLocal,
218220
- shouldUseLocalIndexBeforeRemote,
218221
- toRepoRelativePath,
218222
218167
  getWorkspaceStatusLines,
218223
218168
  runStatusCommand,
218224
218169
  resolveGatewayModel,
@@ -2,7 +2,7 @@ import{createRequire as __cmr}from"node:module";import{fileURLToPath as __f2p}fr
2
2
  import {
3
3
  readMcpServerConfigs,
4
4
  readPriorityResources
5
- } from "./chunk-GGIXJZYK.js";
5
+ } from "./chunk-57JG7UZE.js";
6
6
 
7
7
  // src/cli-agent/chat/mcp-tools/mcp-tool-client.ts
8
8
  import { existsSync } from "fs";
@@ -46,8 +46,8 @@ var CodeMapMcpToolClient = class {
46
46
  getExtraServerConfigs() {
47
47
  return Object.fromEntries(this._extraConfigs);
48
48
  }
49
- async connectExtras() {
50
- const configs = await readMcpServerConfigs();
49
+ async connectExtras(globalMcpServers) {
50
+ const configs = await readMcpServerConfigs(process.cwd(), globalMcpServers);
51
51
  for (const [name, config] of configs) {
52
52
  this._extraConfigs.set(name, config);
53
53
  }
@@ -189,25 +189,36 @@ function resolvePackageRuntime() {
189
189
  function resolveServerCommand(runtime) {
190
190
  const { packageRoot, isSourceRuntime } = runtime;
191
191
  if (isSourceRuntime) {
192
- return {
193
- command: process.execPath,
194
- args: [
195
- require2.resolve("tsx/cli"),
196
- path.join(packageRoot, "src", "index.ts")
197
- ]
198
- };
192
+ const mcpSrcEntry = path.join(
193
+ path.dirname(packageRoot),
194
+ "mcp",
195
+ "src",
196
+ "index.ts"
197
+ );
198
+ if (existsSync(mcpSrcEntry)) {
199
+ return {
200
+ command: process.execPath,
201
+ args: [require2.resolve("tsx/cli"), mcpSrcEntry]
202
+ };
203
+ }
199
204
  }
200
- const distEntry = path.join(packageRoot, "dist", "index.js");
201
- if (existsSync(distEntry)) {
202
- return { command: process.execPath, args: [distEntry] };
205
+ try {
206
+ const mcpEntry = require2.resolve("@codemap-ai/mcp");
207
+ return { command: process.execPath, args: [mcpEntry] };
208
+ } catch {
209
+ const mcpDistEntry = path.join(
210
+ path.dirname(packageRoot),
211
+ "mcp",
212
+ "dist",
213
+ "index.js"
214
+ );
215
+ if (existsSync(mcpDistEntry)) {
216
+ return { command: process.execPath, args: [mcpDistEntry] };
217
+ }
203
218
  }
204
- return {
205
- command: process.execPath,
206
- args: [
207
- require2.resolve("tsx/cli"),
208
- path.join(packageRoot, "src", "index.ts")
209
- ]
210
- };
219
+ throw new Error(
220
+ "Cannot locate CodeMap MCP server. Ensure @codemap-ai/mcp is installed."
221
+ );
211
222
  }
212
223
 
213
224
  export {
@@ -10,21 +10,21 @@ import {
10
10
  removeMcpServerEntry,
11
11
  require_dist,
12
12
  saveMcpServerEntry
13
- } from "./chunk-GGIXJZYK.js";
13
+ } from "./chunk-57JG7UZE.js";
14
14
  import {
15
15
  __toESM,
16
16
  clearGlobalAuthConfig,
17
17
  createCodeMapClient,
18
+ findMonorepoRoot,
18
19
  loadConfig,
19
20
  startMcpLogin,
20
21
  tryOpenLoginBrowser,
21
22
  waitForLoginAuthorization
22
- } from "./chunk-AXGGL47C.js";
23
+ } from "./chunk-4F6G2Q7W.js";
23
24
 
24
25
  // src/cli-agent/core/convention-synthesizer.ts
25
26
  import { readFile, writeFile, mkdir, stat, readdir } from "fs/promises";
26
27
  import { createHash } from "crypto";
27
- import { spawnSync } from "child_process";
28
28
  import path from "path";
29
29
  var CONVENTION_SOURCES = [
30
30
  { label: "Claude Code", paths: ["CLAUDE.md", ".claude/CLAUDE.md"] },
@@ -40,15 +40,14 @@ var RULE_SOURCES = [
40
40
  { label: "Claude Code rules", paths: [".claude/rules/*.md"] }
41
41
  ];
42
42
  var SKILL_DIRS = [".claude/skills", ".codex/skills"];
43
- function getWorkspaceRoot() {
44
- const r = spawnSync("git", ["rev-parse", "--show-toplevel"], { encoding: "utf8", cwd: process.cwd() });
45
- return r.stdout?.trim() || process.cwd();
43
+ async function getWorkspaceRoot() {
44
+ return findMonorepoRoot(process.cwd());
46
45
  }
47
- function dotCodemap() {
48
- return path.join(getWorkspaceRoot(), ".codemap");
46
+ async function dotCodemap() {
47
+ return path.join(await getWorkspaceRoot(), ".codemap");
49
48
  }
50
- function cachePaths() {
51
- const dir = dotCodemap();
49
+ async function cachePaths() {
50
+ const dir = await dotCodemap();
52
51
  return {
53
52
  conventions: { md: path.join(dir, "synthesized-conventions.md"), meta: path.join(dir, "conventions-meta.json") },
54
53
  rules: { md: path.join(dir, "synthesized-rules.md"), meta: path.join(dir, "rules-meta.json") },
@@ -156,7 +155,7 @@ async function loadCache(paths, hash) {
156
155
  }
157
156
  async function saveCache(paths, content, hash, files) {
158
157
  const meta = { hash, scannedFiles: files.map((f) => f.filePath), tokenCount: estimateTokens(content), synthesizedAt: Date.now() };
159
- await mkdir(dotCodemap(), { recursive: true });
158
+ await mkdir(await dotCodemap(), { recursive: true });
160
159
  await Promise.all([writeFile(paths.md, content, "utf8"), writeFile(paths.meta, JSON.stringify(meta, null, 2), "utf8")]);
161
160
  }
162
161
  async function stream(provider, model, prompt, userContent) {
@@ -229,10 +228,10 @@ _[Truncated \u2014 increase \`conventionMaxTokens\` in .codemap/agent-context.js
229
228
  return final;
230
229
  }
231
230
  async function loadOrSynthesizeAll(provider, model, forceRefresh = false) {
232
- const root = getWorkspaceRoot();
231
+ const root = await getWorkspaceRoot();
233
232
  const config = await readConfig(root);
234
233
  const maxTokens = config.conventionMaxTokens ?? null;
235
- const cp = cachePaths();
234
+ const cp = await cachePaths();
236
235
  const [conventionFiles, ruleFiles, skillFiles] = await Promise.all([
237
236
  scanSources(root, CONVENTION_SOURCES),
238
237
  scanSources(root, RULE_SOURCES),
@@ -251,7 +250,7 @@ async function refreshAll(provider, model) {
251
250
  return loadOrSynthesizeAll(provider, model, true);
252
251
  }
253
252
  async function getCachedContext() {
254
- const cp = cachePaths();
253
+ const cp = await cachePaths();
255
254
  const [conventions, rules, skills] = await Promise.all([
256
255
  readFile(cp.conventions.md, "utf8").then((s) => s.trim() || null).catch(() => null),
257
256
  readFile(cp.rules.md, "utf8").then((s) => s.trim() || null).catch(() => null),
@@ -1242,19 +1241,19 @@ _/conventions refresh \u2014 re-synthesize from source files_`);
1242
1241
  };
1243
1242
 
1244
1243
  // src/cli-agent/chat/ui/pi-tui/clipboard.ts
1245
- import { spawnSync as spawnSync2 } from "child_process";
1244
+ import { spawnSync } from "child_process";
1246
1245
  function copyToClipboard(text) {
1247
1246
  try {
1248
1247
  if (process.platform === "darwin") {
1249
- return spawnSync2("pbcopy", { input: text, encoding: "utf8" }).status === 0;
1248
+ return spawnSync("pbcopy", { input: text, encoding: "utf8" }).status === 0;
1250
1249
  }
1251
1250
  if (process.platform === "linux") {
1252
- if (spawnSync2("xclip", ["-selection", "clipboard"], { input: text, encoding: "utf8" }).status === 0) return true;
1253
- if (spawnSync2("xsel", ["--clipboard", "--input"], { input: text, encoding: "utf8" }).status === 0) return true;
1254
- if (spawnSync2("wl-copy", [], { input: text, encoding: "utf8" }).status === 0) return true;
1251
+ if (spawnSync("xclip", ["-selection", "clipboard"], { input: text, encoding: "utf8" }).status === 0) return true;
1252
+ if (spawnSync("xsel", ["--clipboard", "--input"], { input: text, encoding: "utf8" }).status === 0) return true;
1253
+ if (spawnSync("wl-copy", [], { input: text, encoding: "utf8" }).status === 0) return true;
1255
1254
  }
1256
1255
  if (process.platform === "win32") {
1257
- return spawnSync2("clip", { input: text, encoding: "utf8" }).status === 0;
1256
+ return spawnSync("clip", { input: text, encoding: "utf8" }).status === 0;
1258
1257
  }
1259
1258
  } catch {
1260
1259
  }