@aabadin/project-memory-context 0.1.3 → 0.1.4

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.
package/cli/setup.mjs CHANGED
@@ -12,15 +12,21 @@ import { installAgentTemplates } from '../src/template-installer.mjs';
12
12
 
13
13
  const packageRoot = dirname(dirname(fileURLToPath(import.meta.url)));
14
14
 
15
+ const AGENT_FLAGS = {
16
+ '--opencode': 'opencode',
17
+ '--claude': 'claude-code',
18
+ '--cursor': 'cursor',
19
+ '--generic': 'generic',
20
+ };
21
+
15
22
  function installGraphify() {
16
23
  const candidates = process.platform === 'win32' ? ['python', 'py'] : ['python3', 'python'];
17
24
  for (const command of candidates) {
18
25
  const result = spawnSync(command, ['-m', 'pip', 'install', 'graphifyy'], { stdio: 'inherit' });
19
26
  if (result.status === 0) return command;
20
27
  }
21
- const pythonUrl = 'https://www.python.org/downloads/';
22
28
  console.warn(`\n⚠ Could not install graphifyy automatically.`);
23
- console.warn(` Python not found? Download it from: ${pythonUrl}`);
29
+ console.warn(` Python not found? Download it from: https://www.python.org/downloads/`);
24
30
  console.warn(` Then run: pip install graphifyy\n`);
25
31
  return null;
26
32
  }
@@ -31,13 +37,13 @@ function spawnCheck(bin, args) {
31
37
  }
32
38
 
33
39
  function parseArgs(args) {
34
- const parsed = { agent: null };
35
- for (let i = 0; i < args.length; i++) {
36
- if (args[i] === '--agent' && args[i + 1]) {
37
- parsed.agent = args[++i];
40
+ const agents = [];
41
+ for (const arg of args) {
42
+ if (AGENT_FLAGS[arg]) {
43
+ agents.push(AGENT_FLAGS[arg]);
38
44
  }
39
45
  }
40
- return parsed;
46
+ return { agents };
41
47
  }
42
48
 
43
49
  const rl = createInterface({ input, output });
@@ -45,7 +51,17 @@ const cwd = resolve(process.cwd());
45
51
 
46
52
  try {
47
53
  console.log('\n─── pmc setup ───────────────────────────────────────\n');
48
- const { agent: requestedAgent } = parseArgs(process.argv.slice(2));
54
+ const { agents: requestedAgents } = parseArgs(process.argv.slice(2));
55
+
56
+ let agents;
57
+ if (requestedAgents.length > 0) {
58
+ agents = [...new Set(requestedAgents)];
59
+ console.log(` Target agents: ${agents.join(', ')}`);
60
+ } else {
61
+ const detected = detectSetupAgentType(cwd);
62
+ agents = [detected];
63
+ console.log(` Auto-detected agent: ${detected}`);
64
+ }
49
65
 
50
66
  const ollamaBaseUrl =
51
67
  (await rl.question('Ollama base URL [http://localhost:11434]: ')).trim() ||
@@ -57,33 +73,33 @@ try {
57
73
 
58
74
  installGraphify();
59
75
 
60
- const agent = detectSetupAgentType(cwd, { requestedAgent });
61
76
  const { globalConfig } = resolveConfigDirs(cwd);
62
- console.log(`\n Detected agent: ${agent}`);
63
77
 
64
78
  const result = await bootstrapProjectInstall({
65
79
  projectRoot: cwd,
66
80
  packageRoot,
67
81
  ollamaBaseUrl,
68
82
  ollamaModel,
69
- agent,
83
+ agents,
70
84
  });
71
85
 
72
- await installAgentTemplates({
73
- projectRoot: cwd,
74
- agent,
75
- packageRoot,
76
- globalConfigDir: agent === 'opencode' ? globalConfig : undefined,
77
- });
78
- console.log(` Installed ${agent} templates.`);
86
+ for (const agent of agents) {
87
+ await installAgentTemplates({
88
+ projectRoot: cwd,
89
+ agent,
90
+ packageRoot,
91
+ globalConfigDir: agent === 'opencode' ? globalConfig : undefined,
92
+ });
93
+ console.log(` ✓ Installed ${agent} templates.`);
94
+ }
79
95
 
80
96
  console.log('\n─── Installation complete ───────────────────────────\n');
81
97
  console.log(` Memory DB path: ${result.installState.memoryDbPath}`);
82
98
  console.log(` Embedding cache: ${result.installState.embeddingCachePath}`);
83
99
  console.log(` MCP config: ${result.configPath}`);
84
100
  console.log(` Command template: ${result.commandPath}`);
101
+ console.log(` Agents configured: ${agents.join(', ')}`);
85
102
 
86
- // Run doctor to surface any remaining issues
87
103
  console.log('\n─── Environment check ───────────────────────────────\n');
88
104
  const env = {
89
105
  ...process.env,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aabadin/project-memory-context",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "description": "Portable project memory context CLI — bootstraps semantic enrichment workflows for any AI coding agent.",
5
5
  "license": "GPL-3.0-or-later",
6
6
  "type": "module",
@@ -1,9 +1,8 @@
1
1
  import { mkdir, readFile, writeFile } from 'node:fs/promises';
2
- import { basename, dirname, join } from 'node:path';
2
+ import { dirname, join } from 'node:path';
3
3
 
4
4
  import { ensureProjectMemoryContextDirs, writeJsonArtifact } from './artifacts.mjs';
5
5
  import { PMC_ENRICHMENT_CONFIG_FILE } from './enrichment-config.mjs';
6
- import { resolveConfigDirs } from './platform.mjs';
7
6
 
8
7
  async function readJson(filePath, fallback) {
9
8
  try {
@@ -63,50 +62,65 @@ async function writeMcpJson(projectRoot, installState) {
63
62
  return mcpPath;
64
63
  }
65
64
 
66
- async function ensureAgentConfigRegistration(projectRoot, installState, agentType) {
67
- if (agentType === 'opencode') {
68
- const opencodeDir = join(projectRoot, '.opencode');
69
- await mkdir(opencodeDir, { recursive: true });
70
- const configPath = join(opencodeDir, 'opencode.json');
71
- const config = await readJson(configPath, { $schema: 'https://opencode.ai/config.json' });
72
- const existing = Array.isArray(config.plugin) ? config.plugin : [];
73
- if (!existing.includes('@aabadin/project-memory-context')) {
74
- config.plugin = [...existing, '@aabadin/project-memory-context'];
75
- }
76
- config.mcp = {
77
- ...(config.mcp ?? {}),
78
- ...buildOpencodeMcpConfig(installState).mcp,
79
- };
80
- await mkdir(dirname(configPath), { recursive: true });
81
- await writeFile(configPath, `${JSON.stringify(config, null, 2)}\n`, 'utf8');
82
- await writeMcpJson(projectRoot, installState);
83
- return configPath;
65
+ async function ensureOpencodeConfig(projectRoot, installState) {
66
+ const opencodeDir = join(projectRoot, '.opencode');
67
+ await mkdir(opencodeDir, { recursive: true });
68
+ const configPath = join(opencodeDir, 'opencode.json');
69
+ const config = await readJson(configPath, { $schema: 'https://opencode.ai/config.json' });
70
+ const existing = Array.isArray(config.plugin) ? config.plugin : [];
71
+ if (!existing.includes('@aabadin/project-memory-context')) {
72
+ config.plugin = [...existing, '@aabadin/project-memory-context'];
84
73
  }
74
+ config.mcp = {
75
+ ...(config.mcp ?? {}),
76
+ ...buildOpencodeMcpConfig(installState).mcp,
77
+ };
78
+ await mkdir(dirname(configPath), { recursive: true });
79
+ await writeFile(configPath, `${JSON.stringify(config, null, 2)}\n`, 'utf8');
80
+ return configPath;
81
+ }
85
82
 
86
- const { projectConfig } = resolveConfigDirs(projectRoot);
87
- const agentDir = basename(projectConfig);
88
-
89
- if (agentDir === '.claude' || agentDir === '.cursor' || agentDir === '.pmc') {
90
- const mcpPath = await writeMcpJson(projectRoot, installState);
91
- const enrichPath = join(projectConfig, PMC_ENRICHMENT_CONFIG_FILE);
92
- const existingConfig = await readJson(enrichPath, {});
93
- const config = {
94
- ...existingConfig,
95
- enrichment: {
96
- ...existingConfig.enrichment,
97
- localModel: {
98
- ...existingConfig.enrichment?.localModel,
99
- baseUrl: installState.ollamaBaseUrl,
100
- model: installState.ollamaModel,
101
- },
83
+ async function ensureEnrichmentConfig(projectRoot, configDir, installState) {
84
+ const enrichPath = join(configDir, PMC_ENRICHMENT_CONFIG_FILE);
85
+ const existingConfig = await readJson(enrichPath, {});
86
+ const config = {
87
+ ...existingConfig,
88
+ enrichment: {
89
+ ...existingConfig.enrichment,
90
+ localModel: {
91
+ ...existingConfig.enrichment?.localModel,
92
+ baseUrl: installState.ollamaBaseUrl,
93
+ model: installState.ollamaModel,
102
94
  },
103
- };
104
- await mkdir(dirname(enrichPath), { recursive: true });
105
- await writeFile(enrichPath, `${JSON.stringify(config, null, 2)}\n`, 'utf8');
106
- return mcpPath;
95
+ },
96
+ };
97
+ await mkdir(dirname(enrichPath), { recursive: true });
98
+ await writeFile(enrichPath, `${JSON.stringify(config, null, 2)}\n`, 'utf8');
99
+ }
100
+
101
+ async function ensureAgentConfigs(projectRoot, installState, agents) {
102
+ let primaryConfigPath = null;
103
+
104
+ for (const agent of agents) {
105
+ if (agent === 'opencode') {
106
+ primaryConfigPath = primaryConfigPath ?? await ensureOpencodeConfig(projectRoot, installState);
107
+ }
108
+ if (agent === 'claude-code') {
109
+ const claudeDir = join(projectRoot, '.claude');
110
+ await mkdir(claudeDir, { recursive: true });
111
+ await ensureEnrichmentConfig(projectRoot, claudeDir, installState);
112
+ primaryConfigPath = primaryConfigPath ?? join(projectRoot, '.mcp.json');
113
+ }
114
+ if (agent === 'cursor') {
115
+ const cursorDir = join(projectRoot, '.cursor');
116
+ await mkdir(cursorDir, { recursive: true });
117
+ await ensureEnrichmentConfig(projectRoot, cursorDir, installState);
118
+ primaryConfigPath = primaryConfigPath ?? join(projectRoot, '.mcp.json');
119
+ }
107
120
  }
108
121
 
109
- return writeMcpJson(projectRoot, installState);
122
+ await writeMcpJson(projectRoot, installState);
123
+ return primaryConfigPath ?? join(projectRoot, '.mcp.json');
110
124
  }
111
125
 
112
126
  async function copyTemplate(packageRoot, templateName, projectRoot) {
@@ -124,8 +138,10 @@ export async function bootstrapProjectInstall({
124
138
  ollamaBaseUrl,
125
139
  ollamaModel,
126
140
  embeddingCachePath,
141
+ agents = [],
127
142
  agent,
128
143
  }) {
144
+ const resolvedAgents = agents.length > 0 ? agents : (agent ? [agent] : ['generic']);
129
145
  const dirs = await ensureProjectMemoryContextDirs(projectRoot);
130
146
  const memoryDbPath = join(dirs.base, 'memory-db');
131
147
  const installState = {
@@ -139,7 +155,7 @@ export async function bootstrapProjectInstall({
139
155
 
140
156
  await mkdir(memoryDbPath, { recursive: true });
141
157
  await writeJsonArtifact(join(dirs.base, 'install.json'), installState);
142
- const configPath = await ensureAgentConfigRegistration(projectRoot, installState, agent);
158
+ const configPath = await ensureAgentConfigs(projectRoot, installState, resolvedAgents);
143
159
  const commandPath = await copyTemplate(packageRoot, 'project-memory-context.md', projectRoot);
144
160
  const workflowPath = await copyTemplate(packageRoot, 'project-memory-context workflow.md', projectRoot);
145
161
 
@@ -148,5 +164,6 @@ export async function bootstrapProjectInstall({
148
164
  configPath,
149
165
  commandPath,
150
166
  workflowPath,
167
+ agents: resolvedAgents,
151
168
  };
152
169
  }