agent-mind 1.0.0

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 (38) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +229 -0
  3. package/bin/cli.js +38 -0
  4. package/package.json +33 -0
  5. package/src/commands/doctor.js +269 -0
  6. package/src/commands/init.js +345 -0
  7. package/src/commands/meta.js +34 -0
  8. package/src/commands/upgrade.js +177 -0
  9. package/src/index.js +18 -0
  10. package/src/utils/detect-tools.js +62 -0
  11. package/src/utils/inject-adapter.js +65 -0
  12. package/src/utils/template.js +103 -0
  13. package/src/utils/version.js +71 -0
  14. package/template/.am-tools/compact.sh +171 -0
  15. package/template/.am-tools/guide.md +274 -0
  16. package/template/.am-tools/health-check.sh +165 -0
  17. package/template/.am-tools/validate.sh +174 -0
  18. package/template/BOOT.md +71 -0
  19. package/template/README.md +109 -0
  20. package/template/VERSION.md +57 -0
  21. package/template/adapters/claude.md +56 -0
  22. package/template/adapters/codex.md +33 -0
  23. package/template/adapters/cursor.md +35 -0
  24. package/template/adapters/gemini.md +32 -0
  25. package/template/config.md +33 -0
  26. package/template/history/episodes/_index.md +13 -0
  27. package/template/history/maintenance-log.md +9 -0
  28. package/template/history/reflections/_index.md +11 -0
  29. package/template/knowledge/domains/_template/failures/_index.md +19 -0
  30. package/template/knowledge/domains/_template/patterns.md +21 -0
  31. package/template/knowledge/insights.md +23 -0
  32. package/template/knowledge/stack/_template.md +20 -0
  33. package/template/protocols/compaction.md +101 -0
  34. package/template/protocols/maintenance.md +99 -0
  35. package/template/protocols/memory-ops.md +89 -0
  36. package/template/protocols/quality-gate.md +66 -0
  37. package/template/protocols/workflow.md +81 -0
  38. package/template/workspace/.gitkeep +0 -0
@@ -0,0 +1,345 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ const readline = require('readline');
4
+ const { execSync } = require('child_process');
5
+ const detectTools = require('../utils/detect-tools');
6
+ const { copyTemplate, replaceVarsInDir } = require('../utils/template');
7
+ const { injectSnippet, getSnippet, hasSnippet } = require('../utils/inject-adapter');
8
+
9
+ /**
10
+ * Handle both TTY and piped stdin modes.
11
+ *
12
+ * TTY mode: Use readline.createInterface directly
13
+ * Piped mode: Read all stdin lines upfront into a buffer, then consume them
14
+ *
15
+ * This fixes the issue where piped stdin loses data when multiple readline
16
+ * interfaces are created/destroyed.
17
+ */
18
+ let rl = null;
19
+ let isTTY = process.stdin.isTTY === true;
20
+ let pipeBuffer = [];
21
+ let pipeIndex = 0;
22
+
23
+ /**
24
+ * Read all stdin lines into buffer (for piped mode only)
25
+ */
26
+ function initPipeBuffer() {
27
+ return new Promise((resolve) => {
28
+ const lines = [];
29
+ process.stdin.setEncoding('utf8');
30
+
31
+ process.stdin.on('data', (chunk) => {
32
+ const allLines = chunk.split('\n');
33
+ allLines.forEach((line) => {
34
+ if (line.length > 0) {
35
+ lines.push(line);
36
+ }
37
+ });
38
+ });
39
+
40
+ process.stdin.on('end', () => {
41
+ pipeBuffer = lines;
42
+ pipeIndex = 0;
43
+ resolve();
44
+ });
45
+ });
46
+ }
47
+
48
+ /**
49
+ * Get next line from pipe buffer
50
+ */
51
+ function getNextPipeLine() {
52
+ if (pipeIndex < pipeBuffer.length) {
53
+ return pipeBuffer[pipeIndex++];
54
+ }
55
+ return '';
56
+ }
57
+
58
+ /**
59
+ * Create and return a shared readline interface (TTY mode only)
60
+ */
61
+ function getRL() {
62
+ if (!rl) {
63
+ rl = readline.createInterface({
64
+ input: process.stdin,
65
+ output: process.stdout,
66
+ });
67
+ }
68
+ return rl;
69
+ }
70
+
71
+ function closeRL() {
72
+ if (rl) {
73
+ rl.close();
74
+ rl = null;
75
+ }
76
+ }
77
+
78
+ /**
79
+ * Interactive prompt - handles both TTY and piped modes
80
+ */
81
+ function prompt(question, defaultValue = '') {
82
+ return new Promise((resolve) => {
83
+ const displayQuestion = defaultValue
84
+ ? `${question} [${defaultValue}]: `
85
+ : `${question}: `;
86
+
87
+ if (isTTY) {
88
+ // TTY mode: use readline
89
+ getRL().question(displayQuestion, (answer) => {
90
+ resolve(answer.trim() || defaultValue);
91
+ });
92
+ } else {
93
+ // Piped mode: get next line from buffer
94
+ const answer = getNextPipeLine();
95
+ resolve(answer.trim() || defaultValue);
96
+ }
97
+ });
98
+ }
99
+
100
+ /**
101
+ * Confirm prompt - returns true/false
102
+ */
103
+ function confirm(question) {
104
+ return new Promise((resolve) => {
105
+ const confirmQuestion = `${question} (y/n): `;
106
+
107
+ if (isTTY) {
108
+ // TTY mode: use readline
109
+ getRL().question(confirmQuestion, (answer) => {
110
+ resolve(
111
+ answer.trim().toLowerCase() === 'y' ||
112
+ answer.trim().toLowerCase() === 'yes'
113
+ );
114
+ });
115
+ } else {
116
+ // Piped mode: get next line from buffer
117
+ const answer = getNextPipeLine();
118
+ resolve(
119
+ answer.trim().toLowerCase() === 'y' ||
120
+ answer.trim().toLowerCase() === 'yes'
121
+ );
122
+ }
123
+ });
124
+ }
125
+
126
+ /**
127
+ * Select from multiple choice
128
+ */
129
+ async function select(question, choices) {
130
+ console.log(`\n${question}`);
131
+ choices.forEach((choice, idx) => {
132
+ console.log(` ${idx + 1}. ${choice}`);
133
+ });
134
+
135
+ while (true) {
136
+ const answer = await prompt('Select', '1');
137
+ const idx = parseInt(answer, 10) - 1;
138
+ if (idx >= 0 && idx < choices.length) {
139
+ return choices[idx];
140
+ }
141
+ console.log('Invalid selection. Please try again.');
142
+ }
143
+ }
144
+
145
+ /**
146
+ * Make shell scripts executable
147
+ */
148
+ function makeExecutable(dirPath) {
149
+ try {
150
+ const toolsDir = path.join(dirPath, '.am-tools');
151
+ if (fs.existsSync(toolsDir)) {
152
+ const files = fs.readdirSync(toolsDir);
153
+ files.forEach((file) => {
154
+ if (file.endsWith('.sh')) {
155
+ const filePath = path.join(toolsDir, file);
156
+ try {
157
+ execSync(`chmod +x "${filePath}"`, { stdio: 'pipe' });
158
+ } catch {
159
+ // Silently fail — Windows doesn't support chmod
160
+ }
161
+ }
162
+ });
163
+ }
164
+ } catch {
165
+ // Silently handle errors
166
+ }
167
+ }
168
+
169
+ /**
170
+ * Parse comma-separated values into array
171
+ */
172
+ function parseCommaList(str) {
173
+ return str
174
+ .split(',')
175
+ .map((item) => item.trim())
176
+ .filter((item) => item.length > 0);
177
+ }
178
+
179
+ async function init() {
180
+ const cwd = process.cwd();
181
+ const agentMindPath = path.join(cwd, '.agent-mind');
182
+
183
+ console.log('\n🚀 Agent Mind Initialization\n');
184
+
185
+ try {
186
+ // Initialize pipe buffer if stdin is piped
187
+ if (!isTTY) {
188
+ await initPipeBuffer();
189
+ }
190
+ // Check if already exists
191
+ if (fs.existsSync(agentMindPath)) {
192
+ console.log('⚠️ Agent Mind is already initialized in this directory.\n');
193
+ const shouldContinue = await confirm(
194
+ 'Continue anyway and reinitialize?'
195
+ );
196
+ if (!shouldContinue) {
197
+ console.log('Initialization cancelled.');
198
+ return;
199
+ }
200
+ console.log('Reinitializing...\n');
201
+ }
202
+
203
+ // Interactive questions
204
+ const dirName = path.basename(cwd);
205
+ const projectName = await prompt('Project name', dirName);
206
+ const projectDescription = await prompt(
207
+ 'Brief project description (optional)',
208
+ ''
209
+ );
210
+
211
+ const primaryTool = await select('Primary LLM tool?', [
212
+ 'Claude Code',
213
+ 'Codex',
214
+ 'Gemini CLI',
215
+ 'Cursor',
216
+ 'Other',
217
+ ]);
218
+
219
+ const domainsInput = await prompt(
220
+ 'Knowledge domains (comma-separated, optional)',
221
+ ''
222
+ );
223
+ const domains = parseCommaList(domainsInput).join(', ');
224
+
225
+ const stackInput = await prompt(
226
+ 'Key technologies (comma-separated, optional)',
227
+ ''
228
+ );
229
+ const stack = parseCommaList(stackInput).join(', ');
230
+
231
+ // Copy template
232
+ console.log('\n📁 Creating Agent Mind structure...');
233
+ try {
234
+ copyTemplate(agentMindPath);
235
+ } catch (error) {
236
+ throw new Error(`Failed to copy template: ${error.message}`);
237
+ }
238
+
239
+ // Replace variables
240
+ const now = new Date();
241
+ const dateStr = now.toISOString().split('T')[0];
242
+
243
+ const variables = {
244
+ PROJECT_NAME: projectName,
245
+ PROJECT_DESCRIPTION: projectDescription || 'No description provided',
246
+ DATE: dateStr,
247
+ PRIMARY_AGENT: primaryTool,
248
+ DOMAINS: domains || '(none yet — add as project evolves)',
249
+ STACK: stack || '(none yet — add as needed)',
250
+ VERSION: getPackageVersion(),
251
+ };
252
+
253
+ replaceVarsInDir(agentMindPath, variables);
254
+
255
+ // Make scripts executable
256
+ makeExecutable(agentMindPath);
257
+
258
+ console.log('✅ Agent Mind structure created\n');
259
+
260
+ // Detect and integrate with existing tools
261
+ console.log('🔍 Checking for existing LLM tool configurations...\n');
262
+ const detectedTools = detectTools(cwd);
263
+
264
+ if (detectedTools.length > 0) {
265
+ console.log(`Found ${detectedTools.length} tool configuration(s):\n`);
266
+
267
+ for (const tool of detectedTools) {
268
+ const shouldIntegrate = await confirm(
269
+ ` Add Agent Mind integration to ${tool.tool} (${tool.configFile})?`
270
+ );
271
+
272
+ if (shouldIntegrate) {
273
+ const result = injectSnippet(tool.path);
274
+ if (result.success) {
275
+ console.log(` ✅ Integrated with ${tool.tool}\n`);
276
+ console.log(' Added snippet:');
277
+ console.log(
278
+ getSnippet()
279
+ .split('\n')
280
+ .map((l) => ' ' + l)
281
+ .join('\n')
282
+ );
283
+ console.log('');
284
+ } else if (result.reason === 'already-present') {
285
+ console.log(
286
+ ` ℹ️ ${tool.tool} already has Agent Mind integration\n`
287
+ );
288
+ } else {
289
+ console.log(` ❌ Failed to integrate: ${result.message}\n`);
290
+ }
291
+ } else {
292
+ console.log(`\n Add this to your ${tool.configFile} manually:\n`);
293
+ console.log(' ---');
294
+ console.log(
295
+ getSnippet()
296
+ .split('\n')
297
+ .map((l) => ' ' + l)
298
+ .join('\n')
299
+ );
300
+ console.log(' ---\n');
301
+ }
302
+ }
303
+ } else {
304
+ console.log(
305
+ 'No existing LLM tool configs found. You can set up integration later.\n'
306
+ );
307
+ console.log('When ready, add this snippet to your tool config');
308
+ console.log('(CLAUDE.md, AGENTS.md, GEMINI.md, or .cursorrules):\n');
309
+ console.log(
310
+ getSnippet()
311
+ .split('\n')
312
+ .map((l) => ' ' + l)
313
+ .join('\n')
314
+ );
315
+ console.log('');
316
+ }
317
+
318
+ // Success message
319
+ console.log('🎉 Agent Mind is ready!\n');
320
+ console.log('Next steps:');
321
+ console.log(' 1. Your agent reads .agent-mind/BOOT.md at every session start');
322
+ console.log(' 2. Review .agent-mind/config.md to customize settings');
323
+ console.log(' 3. Run `agent-mind doctor` anytime to check memory health\n');
324
+ } finally {
325
+ closeRL();
326
+ }
327
+ }
328
+
329
+ /**
330
+ * Get package version
331
+ */
332
+ function getPackageVersion() {
333
+ try {
334
+ const packageJsonPath = path.join(__dirname, '../../package.json');
335
+ const content = fs.readFileSync(packageJsonPath, 'utf8');
336
+ const pkg = JSON.parse(content);
337
+ return pkg.version;
338
+ } catch {
339
+ return '1.0.0';
340
+ }
341
+ }
342
+
343
+ module.exports = {
344
+ init,
345
+ };
@@ -0,0 +1,34 @@
1
+ const { getPackageVersion } = require('../utils/version');
2
+
3
+ async function version() {
4
+ const ver = getPackageVersion();
5
+ console.log(`agent-mind ${ver}`);
6
+ }
7
+
8
+ async function help() {
9
+ console.log(`
10
+ Agent Mind - Cognitive memory system for LLM agents
11
+
12
+ USAGE:
13
+ agent-mind <command> [options]
14
+
15
+ COMMANDS:
16
+ init Initialize Agent Mind in your project
17
+ upgrade Upgrade Agent Mind to the latest version
18
+ doctor Check Agent Mind health and integrity
19
+ version Show Agent Mind version
20
+ help Show this help message
21
+
22
+ EXAMPLES:
23
+ agent-mind init # Start interactive setup
24
+ agent-mind upgrade # Update existing Agent Mind
25
+ agent-mind doctor # Check system health
26
+
27
+ Learn more at: https://github.com/shikhar1verma/agent-mind
28
+ `);
29
+ }
30
+
31
+ module.exports = {
32
+ version,
33
+ help
34
+ };
@@ -0,0 +1,177 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ const readline = require('readline');
4
+ const { getPackageVersion, getCurrentVersion } = require('../utils/version');
5
+ const { copyTemplate, replaceVars } = require('../utils/template');
6
+
7
+ /**
8
+ * Confirm prompt - returns true/false
9
+ */
10
+ function confirm(question) {
11
+ return new Promise(resolve => {
12
+ const rl = readline.createInterface({
13
+ input: process.stdin,
14
+ output: process.stdout
15
+ });
16
+
17
+ rl.question(`${question} (y/n): `, answer => {
18
+ rl.close();
19
+ resolve(answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes');
20
+ });
21
+ });
22
+ }
23
+
24
+ /**
25
+ * List of core files that should be updated (not user files)
26
+ */
27
+ const CORE_FILES = [
28
+ 'BOOT.md',
29
+ 'VERSION.md',
30
+ 'protocols/compaction.md',
31
+ 'protocols/maintenance.md',
32
+ 'protocols/workflow.md',
33
+ 'protocols/quality-gate.md',
34
+ 'protocols/memory-ops.md',
35
+ 'adapters/claude.md',
36
+ 'adapters/codex.md',
37
+ 'adapters/gemini.md',
38
+ 'adapters/cursor.md'
39
+ ];
40
+
41
+ /**
42
+ * Recursively copy core files only
43
+ */
44
+ function copyOnlyCore(srcDir, destDir) {
45
+ if (!fs.existsSync(destDir)) {
46
+ fs.mkdirSync(destDir, { recursive: true });
47
+ }
48
+
49
+ function isCoreFile(relativePath) {
50
+ return CORE_FILES.some(core => {
51
+ // Handle both exact matches and directory prefixes
52
+ return relativePath === core || relativePath.startsWith(core + '/');
53
+ });
54
+ }
55
+
56
+ function copyDirFiltered(src, dest, basePath = '') {
57
+ const items = fs.readdirSync(src);
58
+
59
+ items.forEach(item => {
60
+ const srcPath = path.join(src, item);
61
+ const destPath = path.join(dest, item);
62
+ const relativePath = basePath ? `${basePath}/${item}` : item;
63
+ const stat = fs.statSync(srcPath);
64
+
65
+ if (stat.isDirectory()) {
66
+ // Check if this directory contains core files
67
+ if (isCoreFile(relativePath)) {
68
+ if (!fs.existsSync(destPath)) {
69
+ fs.mkdirSync(destPath, { recursive: true });
70
+ }
71
+ copyDirFiltered(srcPath, destPath, relativePath);
72
+ }
73
+ } else if (isCoreFile(relativePath)) {
74
+ fs.copyFileSync(srcPath, destPath);
75
+ }
76
+ });
77
+ }
78
+
79
+ copyDirFiltered(srcDir, destDir);
80
+ }
81
+
82
+ /**
83
+ * Make shell scripts executable
84
+ */
85
+ function makeExecutable(dirPath) {
86
+ try {
87
+ const toolsDir = path.join(dirPath, '.am-tools');
88
+ if (fs.existsSync(toolsDir)) {
89
+ const files = fs.readdirSync(toolsDir);
90
+ files.forEach(file => {
91
+ if (file.endsWith('.sh')) {
92
+ const filePath = path.join(toolsDir, file);
93
+ try {
94
+ const { execSync } = require('child_process');
95
+ execSync(`chmod +x "${filePath}"`, { stdio: 'pipe' });
96
+ } catch {
97
+ // Silently fail - Windows doesn't support chmod
98
+ }
99
+ }
100
+ });
101
+ }
102
+ } catch (error) {
103
+ // Silently handle errors
104
+ }
105
+ }
106
+
107
+ async function upgrade() {
108
+ const cwd = process.cwd();
109
+ const agentMindPath = path.join(cwd, '.agent-mind');
110
+
111
+ console.log('\n⬆️ Agent Mind Upgrade\n');
112
+
113
+ // Check if Agent Mind exists
114
+ if (!fs.existsSync(agentMindPath)) {
115
+ throw new Error('Agent Mind not found. Run "agent-mind init" first.');
116
+ }
117
+
118
+ // Get versions
119
+ const currentVersion = getCurrentVersion(agentMindPath);
120
+ const packageVersion = getPackageVersion();
121
+
122
+ console.log(`Current version: ${currentVersion}`);
123
+ console.log(`Package version: ${packageVersion}\n`);
124
+
125
+ if (currentVersion === packageVersion) {
126
+ console.log('✅ Already up to date!');
127
+ return;
128
+ }
129
+
130
+ // Show what will be updated
131
+ console.log('Files that will be updated:');
132
+ CORE_FILES.forEach(file => {
133
+ console.log(` • ${file}`);
134
+ });
135
+ console.log('\nNote: Your user files (config.md, knowledge/, workspace/, history/) are never touched.\n');
136
+
137
+ // Ask for confirmation
138
+ const shouldProceed = await confirm('Continue upgrade?');
139
+ if (!shouldProceed) {
140
+ console.log('Upgrade cancelled.');
141
+ return;
142
+ }
143
+
144
+ // Perform upgrade
145
+ console.log('\n📦 Upgrading...');
146
+
147
+ const templatePath = path.join(__dirname, '../../template');
148
+ if (!fs.existsSync(templatePath)) {
149
+ throw new Error('Template directory not found');
150
+ }
151
+
152
+ // Copy only core files
153
+ copyOnlyCore(templatePath, agentMindPath);
154
+
155
+ // Update VERSION.md
156
+ const versionPath = path.join(agentMindPath, 'VERSION.md');
157
+ const now = new Date().toISOString().split('T')[0];
158
+
159
+ replaceVars(versionPath, {
160
+ VERSION: packageVersion,
161
+ DATE: now
162
+ });
163
+
164
+ // Make scripts executable
165
+ makeExecutable(agentMindPath);
166
+
167
+ console.log(`✅ Upgraded to ${packageVersion}\n`);
168
+ console.log('Updated files:');
169
+ CORE_FILES.forEach(file => {
170
+ console.log(` ✓ ${file}`);
171
+ });
172
+ console.log('\nYour project data is safe and unchanged.\n');
173
+ }
174
+
175
+ module.exports = {
176
+ upgrade
177
+ };
package/src/index.js ADDED
@@ -0,0 +1,18 @@
1
+ // Agent Mind CLI main router
2
+ // Exports command modules for dispatch
3
+
4
+ module.exports = {
5
+ commands: {
6
+ init: require('./commands/init').init,
7
+ upgrade: require('./commands/upgrade').upgrade,
8
+ doctor: require('./commands/doctor').doctor,
9
+ version: require('./commands/meta').version,
10
+ help: require('./commands/meta').help
11
+ },
12
+ utils: {
13
+ detectTools: require('./utils/detect-tools'),
14
+ template: require('./utils/template'),
15
+ version: require('./utils/version'),
16
+ injectAdapter: require('./utils/inject-adapter')
17
+ }
18
+ };
@@ -0,0 +1,62 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+
4
+ /**
5
+ * Detect which LLM tool configuration files exist in the current directory
6
+ * @param {string} [cwd=process.cwd()] - Directory to search
7
+ * @returns {Array<{tool: string, path: string}>} - Detected tools with their config paths
8
+ */
9
+ function detectTools(cwd = process.cwd()) {
10
+ const detected = [];
11
+
12
+ // Check for Claude Code
13
+ const claudePath = path.join(cwd, 'CLAUDE.md');
14
+ if (fs.existsSync(claudePath)) {
15
+ detected.push({
16
+ tool: 'Claude Code',
17
+ path: claudePath,
18
+ configFile: 'CLAUDE.md'
19
+ });
20
+ }
21
+
22
+ // Check for Codex
23
+ const agentsPath = path.join(cwd, 'AGENTS.md');
24
+ if (fs.existsSync(agentsPath)) {
25
+ detected.push({
26
+ tool: 'Codex',
27
+ path: agentsPath,
28
+ configFile: 'AGENTS.md'
29
+ });
30
+ }
31
+
32
+ // Check for Gemini CLI
33
+ const geminiPath = path.join(cwd, 'GEMINI.md');
34
+ if (fs.existsSync(geminiPath)) {
35
+ detected.push({
36
+ tool: 'Gemini CLI',
37
+ path: geminiPath,
38
+ configFile: 'GEMINI.md'
39
+ });
40
+ }
41
+
42
+ // Check for Cursor
43
+ const cursorRulesPath = path.join(cwd, '.cursorrules');
44
+ const cursorRulesDirPath = path.join(cwd, '.cursor', 'rules');
45
+ if (fs.existsSync(cursorRulesPath)) {
46
+ detected.push({
47
+ tool: 'Cursor',
48
+ path: cursorRulesPath,
49
+ configFile: '.cursorrules'
50
+ });
51
+ } else if (fs.existsSync(cursorRulesDirPath)) {
52
+ detected.push({
53
+ tool: 'Cursor',
54
+ path: cursorRulesDirPath,
55
+ configFile: '.cursor/rules/'
56
+ });
57
+ }
58
+
59
+ return detected;
60
+ }
61
+
62
+ module.exports = detectTools;
@@ -0,0 +1,65 @@
1
+ const fs = require('fs');
2
+
3
+ const SNIPPET = `## Agent Mind Memory System
4
+ This project uses Agent Mind for structured memory management.
5
+ At the start of every session, read \`.agent-mind/BOOT.md\` and follow its protocols.
6
+ Use \`.agent-mind/workspace/\` as working memory for the current task.
7
+ After completing a task, follow \`.agent-mind/protocols/compaction.md\`.
8
+ When asked about memory health, follow \`.agent-mind/protocols/maintenance.md\`.`;
9
+
10
+ /**
11
+ * Get the Agent Mind adapter snippet
12
+ */
13
+ function getSnippet() {
14
+ return SNIPPET;
15
+ }
16
+
17
+ /**
18
+ * Check if the snippet is already present in the file
19
+ * @param {string} filePath - Path to config file
20
+ */
21
+ function hasSnippet(filePath) {
22
+ try {
23
+ const content = fs.readFileSync(filePath, 'utf8');
24
+ return content.includes('Agent Mind Memory System');
25
+ } catch (error) {
26
+ return false;
27
+ }
28
+ }
29
+
30
+ /**
31
+ * Inject the Agent Mind snippet into a tool config file
32
+ * @param {string} filePath - Path to config file
33
+ */
34
+ function injectSnippet(filePath) {
35
+ try {
36
+ if (hasSnippet(filePath)) {
37
+ return {
38
+ success: false,
39
+ reason: 'already-present',
40
+ message: 'Agent Mind snippet already present in file'
41
+ };
42
+ }
43
+
44
+ const content = fs.readFileSync(filePath, 'utf8');
45
+ const newContent = content + '\n\n' + SNIPPET + '\n';
46
+ fs.writeFileSync(filePath, newContent, 'utf8');
47
+
48
+ return {
49
+ success: true,
50
+ message: 'Agent Mind snippet injected successfully'
51
+ };
52
+ } catch (error) {
53
+ return {
54
+ success: false,
55
+ reason: 'write-error',
56
+ message: `Failed to inject snippet: ${error.message}`
57
+ };
58
+ }
59
+ }
60
+
61
+ module.exports = {
62
+ getSnippet,
63
+ hasSnippet,
64
+ injectSnippet
65
+ };