claude-flow 3.5.49 → 3.5.50

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-flow",
3
- "version": "3.5.49",
3
+ "version": "3.5.50",
4
4
  "description": "Ruflo - Enterprise AI agent orchestration for Claude Code. Deploy 60+ specialized agents in coordinated swarms with self-learning, fault-tolerant consensus, vector memory, and MCP integration",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",
@@ -642,12 +642,48 @@ async function createDirectories(targetDir, options, result) {
642
642
  */
643
643
  async function writeSettings(targetDir, options, result) {
644
644
  const settingsPath = path.join(targetDir, '.claude', 'settings.json');
645
+ const generated = JSON.parse(generateSettingsJson(options));
645
646
  if (fs.existsSync(settingsPath) && !options.force) {
646
- result.skipped.push('.claude/settings.json');
647
+ // Merge hooks/env/permissions into existing settings instead of skipping
648
+ try {
649
+ const existing = JSON.parse(fs.readFileSync(settingsPath, 'utf-8'));
650
+ let merged = false;
651
+ // Merge hooks (the critical missing piece — #1484)
652
+ if (generated.hooks && !existing.hooks) {
653
+ existing.hooks = generated.hooks;
654
+ merged = true;
655
+ }
656
+ // Merge env vars (for CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS etc.)
657
+ if (generated.env) {
658
+ existing.env = { ...(existing.env || {}), ...generated.env };
659
+ merged = true;
660
+ }
661
+ // Merge permissions (add ruflo allow rules)
662
+ if (generated.permissions?.allow) {
663
+ const existingAllow = existing.permissions?.allow || [];
664
+ const newRules = generated.permissions.allow.filter((r) => !existingAllow.includes(r));
665
+ if (newRules.length > 0) {
666
+ existing.permissions = existing.permissions || {};
667
+ existing.permissions.allow = [...existingAllow, ...newRules];
668
+ merged = true;
669
+ }
670
+ }
671
+ if (merged) {
672
+ fs.writeFileSync(settingsPath, JSON.stringify(existing, null, 2), 'utf-8');
673
+ result.created.files.push('.claude/settings.json (merged hooks)');
674
+ }
675
+ else {
676
+ result.skipped.push('.claude/settings.json');
677
+ }
678
+ }
679
+ catch {
680
+ // Existing file is corrupt — overwrite
681
+ fs.writeFileSync(settingsPath, JSON.stringify(generated, null, 2), 'utf-8');
682
+ result.created.files.push('.claude/settings.json');
683
+ }
647
684
  return;
648
685
  }
649
- const content = generateSettingsJson(options);
650
- fs.writeFileSync(settingsPath, content, 'utf-8');
686
+ fs.writeFileSync(settingsPath, JSON.stringify(generated, null, 2), 'utf-8');
651
687
  result.created.files.push('.claude/settings.json');
652
688
  }
653
689
  /**
@@ -358,7 +358,8 @@ export async function bridgeSearchEntries(options) {
358
358
  if (!ctx)
359
359
  return null;
360
360
  try {
361
- const { query: queryStr, namespace = 'default', limit = 10, threshold = 0.3 } = options;
361
+ const { query: queryStr, namespace, limit = 10, threshold = 0.3 } = options;
362
+ const effectiveNamespace = namespace || 'all';
362
363
  const startTime = Date.now();
363
364
  // Generate query embedding
364
365
  let queryEmbedding = null;
@@ -373,7 +374,7 @@ export async function bridgeSearchEntries(options) {
373
374
  // Fall back to keyword search
374
375
  }
375
376
  // better-sqlite3: .prepare().all() returns array of objects
376
- const nsFilter = namespace !== 'all'
377
+ const nsFilter = effectiveNamespace !== 'all'
377
378
  ? `AND namespace = ?`
378
379
  : '';
379
380
  let rows;
@@ -384,7 +385,7 @@ export async function bridgeSearchEntries(options) {
384
385
  WHERE status = 'active' ${nsFilter}
385
386
  LIMIT 1000
386
387
  `);
387
- rows = namespace !== 'all' ? stmt.all(namespace) : stmt.all();
388
+ rows = effectiveNamespace !== 'all' ? stmt.all(effectiveNamespace) : stmt.all();
388
389
  }
389
390
  catch {
390
391
  return null;
@@ -356,14 +356,14 @@ export async function getHNSWIndex(options) {
356
356
  return null; // VectorDb not found
357
357
  }
358
358
  const { VectorDb } = ruvectorCore;
359
- // Persistent storage paths
360
- const swarmDir = path.join(process.cwd(), '.swarm');
359
+ // Persistent storage paths — resolve to absolute to survive CWD changes
360
+ const swarmDir = path.resolve(process.cwd(), '.swarm');
361
361
  if (!fs.existsSync(swarmDir)) {
362
362
  fs.mkdirSync(swarmDir, { recursive: true });
363
363
  }
364
364
  const hnswPath = path.join(swarmDir, 'hnsw.index');
365
365
  const metadataPath = path.join(swarmDir, 'hnsw.metadata.json');
366
- const dbPath = options?.dbPath || path.join(swarmDir, 'memory.db');
366
+ const dbPath = options?.dbPath ? path.resolve(options.dbPath) : path.join(swarmDir, 'memory.db');
367
367
  // Create HNSW index with persistent storage
368
368
  // @ruvector/core uses string enum for distanceMetric: 'Cosine', 'Euclidean', 'DotProduct', 'Manhattan'
369
369
  const db = new VectorDb({
@@ -1694,8 +1694,8 @@ export async function storeEntry(options) {
1694
1694
  }
1695
1695
  // Fallback: raw sql.js
1696
1696
  const { key, value, namespace = 'default', generateEmbeddingFlag = true, tags = [], ttl, dbPath: customPath, upsert = false } = options;
1697
- const swarmDir = path.join(process.cwd(), '.swarm');
1698
- const dbPath = customPath || path.join(swarmDir, 'memory.db');
1697
+ const swarmDir = path.resolve(process.cwd(), '.swarm');
1698
+ const dbPath = customPath ? path.resolve(customPath) : path.join(swarmDir, 'memory.db');
1699
1699
  try {
1700
1700
  if (!fs.existsSync(dbPath)) {
1701
1701
  return { success: false, id: '', error: 'Database not initialized. Run: claude-flow memory init' };
@@ -1785,9 +1785,10 @@ export async function searchEntries(options) {
1785
1785
  return bridgeResult;
1786
1786
  }
1787
1787
  // Fallback: raw sql.js
1788
- const { query, namespace = 'default', limit = 10, threshold = 0.3, dbPath: customPath } = options;
1789
- const swarmDir = path.join(process.cwd(), '.swarm');
1790
- const dbPath = customPath || path.join(swarmDir, 'memory.db');
1788
+ const { query, namespace, limit = 10, threshold = 0.3, dbPath: customPath } = options;
1789
+ const effectiveNamespace = namespace || 'all';
1790
+ const swarmDir = path.resolve(process.cwd(), '.swarm');
1791
+ const dbPath = customPath ? path.resolve(customPath) : path.join(swarmDir, 'memory.db');
1791
1792
  const startTime = Date.now();
1792
1793
  try {
1793
1794
  if (!fs.existsSync(dbPath)) {
@@ -1799,7 +1800,7 @@ export async function searchEntries(options) {
1799
1800
  const queryEmb = await generateEmbedding(query);
1800
1801
  const queryEmbedding = queryEmb.embedding;
1801
1802
  // Try HNSW search first (150x faster)
1802
- const hnswResults = await searchHNSWIndex(queryEmbedding, { k: limit, namespace });
1803
+ const hnswResults = await searchHNSWIndex(queryEmbedding, { k: limit, namespace: effectiveNamespace });
1803
1804
  if (hnswResults && hnswResults.length > 0) {
1804
1805
  // Filter by threshold
1805
1806
  const filtered = hnswResults.filter(r => r.score >= threshold);
@@ -1815,11 +1816,11 @@ export async function searchEntries(options) {
1815
1816
  const fileBuffer = fs.readFileSync(dbPath);
1816
1817
  const db = new SQL.Database(fileBuffer);
1817
1818
  // Get entries with embeddings
1818
- const searchStmt = db.prepare(namespace !== 'all'
1819
+ const searchStmt = db.prepare(effectiveNamespace !== 'all'
1819
1820
  ? `SELECT id, key, namespace, content, embedding FROM memory_entries WHERE status = 'active' AND namespace = ? LIMIT 1000`
1820
1821
  : `SELECT id, key, namespace, content, embedding FROM memory_entries WHERE status = 'active' LIMIT 1000`);
1821
- if (namespace !== 'all') {
1822
- searchStmt.bind([namespace]);
1822
+ if (effectiveNamespace !== 'all') {
1823
+ searchStmt.bind([effectiveNamespace]);
1823
1824
  }
1824
1825
  const searchRows = [];
1825
1826
  while (searchStmt.step()) {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@claude-flow/cli",
3
- "version": "3.5.49",
3
+ "version": "3.5.50",
4
4
  "type": "module",
5
5
  "description": "Ruflo CLI - Enterprise AI agent orchestration with 60+ specialized agents, swarm coordination, MCP server, self-learning hooks, and vector memory for Claude Code",
6
6
  "main": "dist/src/index.js",